j--
j--

Reputation: 5676

Sort records by date in shell using standard UNIX utilities sed, awk, sort, etc

I have two text files, records and dates:

records

a
b
c
d
e

dates

Fri Jul 15 23:20:01
Thu Jul 14 12:03:53
Mon Jul 10 10:11:35
Mon Jul 10 10:11:20
Mon Jul 10 10:11:15

Each line in records matches a line in dates. Both files are also always sorted chronologically.

I would like to display the following:

Fri Jul 15
  a

Thu Jul 14
  b

Mon Jul 10
  c
  d
  e

I can imagine a simple algorithm that loops through each line in records and compares the corresponding date in dates with the last date I checked, but this would be involved and I would like to know if it can be accomplished in a pipeline using awk, sed, sort, etc., without bashisms.

Upvotes: 0

Views: 372

Answers (2)

Tiago Lopo
Tiago Lopo

Reputation: 7959

You can try this:

paste -d:  <(awk '{print $1,$2,$3}' dates) records | awk -F: '$1!=prev{print $1"\n\t"$2;prev=$1;next} $1==prev{print "\t"$2}'
Fri Jul 15
    a
Thu Jul 14
    b
Mon Jul 10
    c
    d
    e

Explanation:

<([command]) : Allows us to use the output of [command] as a file

paste -d: <([awk] dates) records : will paste output of the awk command with the records file using : as separator ex: Fri Jul 15:a

And the last awk command:

awk -F: '
         # If we have not seen date print date,new line,tab and record
         $1!=prev {print $1"\n\t"$2;prev=$1;next} 

         #if we have seen date print tab and record
         $1==prev{print "\t"$2}
        '

As Ed Morton pointed out in the comments, last awk command can be shorter:

awk  -F: '{print ($1==prev ? "" : $1"\n") "\t"$2; prev=$1}'

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 203985

$ cat tst.awk
NR==FNR {
    sub(/ [0-9:]+$/,"")
    dates[NR] = $0
    next
}
{
    curr = dates[FNR]
    if (curr != prev) {
        print curr
    }
    print "  " $0
    prev = curr
}

$ awk -f tst.awk dates records
Fri Jul 15
  a
Thu Jul 14
  b
Mon Jul 10
  c
  d
  e

Upvotes: 4

Related Questions