Kornshell - How to print blank spaces properly sed and cal
Question
I am currently using this command,
cal $month $year | sed -n '1,2p'
cal $month $year | sed -n '3,$p' |
sed -n '/'$day'/{s/.*\('$day'.*\)/\1/p; :a; n; p; ba; }'
And it is giving me this output
March 2014
Su Mo Tu We Th Fr Sa
4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
How can I get this output?
March 2014
Su Mo Tu We Th Fr Sa
4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
FYI: $month $year $day
is using the current date.
I am trying to avoid using a set number of spaces because if it was a different day then the numbers would not match up with the spaces.
EDIT: For Jonathan Leffler
Thank you! This is getting really close to the output I am looking for. The sample output you posted is exactly what I am looking for but after trying your code. It gave me this instead.
March 2014
Su Mo Tu We Th Fr Sa
2 3 4 5 Q6 7 8
6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
How am I able to remove the line with the Q? I assume this is coming from the 2nd s///
you provided
EDIT:
Figure it out, Thank you for your help!
Solution
This script works (I think):
year=2014
month=3
day=6
cal $month $year | sed -n -e '
1,2p
3,${/'$day'/{
s/^\(.*\)\('$day'.*\)/\1Q\2/
:blanks
s/^\( *\)[^ Q]/\1 /g
t blanks
s/Q//p
:a
n
p
ba
}
}'
Sample output:
March 2014
Su Mo Tu We Th Fr Sa
6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
- The first
s///
command puts a Q (not part of the output fromcal
) before the day that you want to keep. - The label
:blanks
, thes///
and thet blanks
replace a string of blanks and a non-blank, non-Q with the string of blanks and another blank, zapping all the non-blank characters before the Q. - The
s/Q//p
removes the marker and prints the line. - The remainder of the code is the same as before (but spread over multiple lines); it gets the next line of input and prints it repeatedly.
OTHER TIPS
An awk
script to acheive the desired effect:
cal.awk:
# Print first two lines (heading)
NR < 3 { print; next }
# Skip weeks in which the last day is before variable 'day'
$NF < day { next }
# Print full weeks if the first day is on or after variable 'day'
$1 >= day { print; next }
# This will be executed for the week on which variable 'day' falls.
{
# Traverse each day
for (i=1; i<=NF; ++i) {
# If current day is on or after variable 'day', print it.
if ($i >= day) {
if ($i < 10) # Check for extra formatting for single digit days
printf(" ");
printf("%d ", $i);
}
else
printf " "; # Formatting for blank days
}
print ""; # Add new line
}
Invocation:
cal $month $year | awk -v day=$day -f cal.awk