#! /bin/sh date +"%w %d %-m %Y" | sed ' 1 { # Weekday in hold space, day of the month in pattern space h s/ .*$// x s/^.* // # Reduce day of month to 1-7, subtracting 7 repeatedly. Each iteration # decrements the tenths digit, lowering the day of the month by either 7 # or 14. The first and third y commands are guaranteed to operate on the # units. :week /^[123]/ { s/^1/a/ s/^2/b/ s/^3/c/ y/9876543210/5432176543/ y/abc/012/ b week } y/89/12/ # Each iteration decrements both day and weekday by 1 # (weekday has wrap-around from 0=Sunday to 6=Saturday) :wday /01/!{ y/234567/123456/ x y/0123456/6012345/ x b wday } # Prepare a calendar for a 28-day month. First add the blanks # depending on the week-day x /^[1-6]/ s/$/ / /^[2-6]/ s/$/ / /^[3-6]/ s/$/ / /^[4-6]/ s/$/ / /^[5-6]/ s/$/ / /^6/ s/$/ / # Then add the header (replacing the week-day) and the days s/^./Sun Mon Tue Wed Thu Fri Sat / s/$/ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 / s/$/ 15 16 17 18 19 20 21 22 23 24 25 26 27 28 / # Store in hold space, waiting for the next cycle h d } 2 { # Pick the number of days in the month /^[469]/ b d30 /^11/ b d30 /^[13578]/ b d31 # February. Get the year. Decide whether we must test the century # or the 2-digit year, and only keep the two relevant digits. s/.* // /..00/ s/..$// /..../ s/^..// # Test divisibility by 4 /[02468][048]/ b d29 /[13579][26]/ b d29 g; b print # Add days if 28 are not enough :d29 g; s/$/ 29/; b print :d30 g; s/$/ 29 30/; b print :d31 g; s/$/ 29 30 31/ # Split the calendar in 27-character lines :print s/\([^\n]\{27\}\) /\1\ /g } '