I have a text file containing birthdays:

1/23 Horace
3/1 Taraneh
7/14 Valerian
11/31 Carmen

I want to display the birthdays from today's date.
For example if today is 4/7 (April 7th):

7/14 Valerian
11/31 Carmen
1/23 Horace
3/1 Taraneh

How to do this in a bash script?

I have found how to split a text file based on a pattern (I could then concatenate the splits in the opposite order) but here the trick is that today's date might be absent, or might be the birthday of several people.

Note: all dates are valid dates.

share|improve this question
up vote 8 down vote accepted

Maybe something like:

date +'%m/%d 0000' |
  sort -nt/ -k1 -k2 - birthdays.txt |
  awk '$2 == "0000" {past_today = 1; next}
       past_today {print; next}
       {next_year = next_year $0 RS}
       END {printf "%s", next_year}'

That is, insert a 04/07 0000 line (date +%-m/%-d would output 4/7 with some date implementations but is not portable, and 04/07 works just as well) before sorting by date, and then have awk move the lines that are before that one to the end.

sort ... - birthdays.txt

sorts both its stdin (represented by -, here a pipe that is fed by date) and the content of birthdays.txt.

We set the key separator to / with -t/, -k1 specifies a sort key that runs from start to end of the line (in essence, -k1 specifies the full line as a sort key), and -k2 a sort key that starts from the first character after the first / to the end of the line, but with -n, those are interpreted as numbers, so only the initial sequence of digits matters.

(the above would work with any Bourne-like shell (including bash), no need to install bash just for that).

share|improve this answer
    
Please explain how does sort combine both the contents of birthdays.txt and the output of date piped into it in a single output. – Tulains Córdova 5 hours ago
    
@TulainsCórdova, see edit. – Stéphane Chazelas 5 hours ago
    
+1 Excelent answer! – Tulains Córdova 5 hours ago

First change "/" in space and sort

sed 's|/| |' data | sort -k1,1n -k2,2n >out.tmp

Next, output the next dates before and the previous after

awk -v m=4 -v d=7 '$1 > m || $1 == m && $2 >= d' out.tmp
awk -v m=4 -v d=7 '$1 < m || $1 == m && $2 <  d' out.tmp
share|improve this answer
    
@NicolasRaoul: strange, it gives me the right answer. Probably a different flavour of "sort". Anyway no problem, you have an accepted answer. – enzotib 9 hours ago
    
Sorry I was wrong, your answer works too, thanks! – Nicolas Raoul 8 hours ago
    
This answer would benefit from an explanation how it works. – David Conrad 1 hour ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.