1

(Adapted from this: Join Manual, Header lines).

I am sorting a file called file1 with this content:

Name   Age
Charlie 34
Alice   25

If I just write:

sort -k2b,2 file1

I get:

Alice   25
Charlie 34
Name   Age

I can exclude the header from the sort like so:

head -1 file1 ;(sed -n '2,$p' file1|sort -k2b,2)

But the example in the gnu manual is this:

( sed -u 1q ; sort -k2b,2 ) < file1

Why does that work?

I would think that I would get this instead from the command-line:

Name   Age
Alice   25
Charlie 34
Name   Age

The sed consumes the first line of stdin, then the sort consumes the rest?

FondDuLac
  • 21
  • 2
  • 3
    *`The sed consumes the first line of stdin, then the sort consumes the rest?`* - yes, `sed` strips the 1st line off stdin and dumps to stdout while the `sort` is fed the rest of stdin and then dumps to stdout – markp-fuso Jan 20 '23 at 20:40
  • 1
    by default `sed` is going to buffer the input so if the volume of input can fit into the initial buffer then `1q` will print the first line and discard the contents of the buffer, which means nothing is passed to `sort`; the `-u` tells `sed` to *not* buffer anything, to read/process one line at a time, so when `sed` hits `q` the rest of stdin is still available to be passed to `sort` – markp-fuso Jan 20 '23 at 20:49
  • 1
    The important concept is that both `sed` and `sort` are reading from the same stream, not independent openings of the file. So `sort` starts reading from where `sed` ended. – Barmar Jan 20 '23 at 20:58
  • 2
    `( head -n 1 ; sort -k2b,2 ) < file` should work too – Diego Torres Milano Jan 20 '23 at 21:05
  • 3
    So should `{ head -n 1 ; sort -k2b,2 ; } < file` with one fewer subprocesses . – Mark Setchell Jan 20 '23 at 21:18
  • 1
    @KamilCuk `read` (by itself) discards the 1st line; perhaps something like `read -r hdr; echo "$hdr";` – markp-fuso Jan 20 '23 at 21:37

1 Answers1

0

You could have sed print the header, then sort the rest.

sed -n '1p' file1; sort <(sed '1d' file1)
Name   Age
Alice   25
Charlie 34
Cole Tierney
  • 9,571
  • 1
  • 27
  • 35