Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I sort the file by the second column from the terminal. The content of the file is:

Nome     Note
------------
Mehdi    0
Sunday   20
Others   10
Shnou    5

Using sort -t' ' -nk2 is not giving me the right result. Also how can I ensure that the content of the file stay sorted?

share|improve this question
add comment

2 Answers

up vote 5 down vote accepted

I think what you're after is something like these:

Method #1: using head & tail

$ (head -n 2 sample.txt; tail -n +3 sample.txt | sort -t' ' -nk2) > a.tmp && mv a.tmp sample.txt

Nome     Note
------------
Mehdi    0
Shnou    5
Others   10
Sunday   20

This takes the first line of the text file, then tails everything after the first 2 lines which is then sorted.

Method #2: just using head

$ (head -n 2; sort -t' ' -nk2) < sample.txt > a.tmp && mv a.tmp sample.txt

Nome     Note
------------
Mehdi    0
Shnou    5
Others   10
Sunday   20

Takes the text file as input, displays just the first line, sort the rest.

It's typically not a good idea to edit files in place. It's possible, but better to use an intermediate file.

Method #3: Doing #2 without an intermediate file

Stealing the idea from @StephaneChazelas you could do the following using the "1<>" notation to open a file for reading & writing, and the improvements he suggested with the sort command.

$ (head -n 2; sort -nk2) < sample.txt 1<> sample.txt

Nome     Note
------------
Mehdi    0
Shnou    5
Others   10
Sunday   20
share|improve this answer
    
but the file remains unchanged, do I have to use an intermediate file? –  user34923 May 10 '13 at 15:02
    
the file became empty –  user34923 May 10 '13 at 15:17
    
Try them now, I opted to use intermediate files. –  slm May 10 '13 at 15:27
    
I think it is better to use head -2 and include the dashed lines as part of the head. They get sorted correctly now but that is probably not the case when using a separator like = = = = ( '=' > '9' > '-' ). –  Anthon May 10 '13 at 16:05
    
@Anthon, good point. –  slm May 10 '13 at 16:06
show 1 more comment

To overwrite the file in place, you can do:

{
  head -n 2 &&
    sort -k2n
} < the-file.txt 1<> the-file.txt

That works because sort has read its input fully before it starts to write its output, so it's fine to write to the file it is reading from. Also its ouput is the same size as its input, so no need to truncate the file in the end.

Note that if you use -t' ' instead of the default separator, each space character in the input would make a new field, so for instance in:

 a 10
b  2

(with a space before a and 2 spaces after b), -t' ' -nk2 (remember -k2 is for from field 2 to end of line, while -k2,2 is field 2 only) would compare "a 10" to " 2" numerically, while -nk2 alone would compare " 10" to "  2" numerically (and numerical comparison ignores leading blanks).

share|improve this answer
    
You're gonna have to explain that magic 8-) –  slm May 10 '13 at 15:31
    
I get the { } is a list. What's going on with the 1<>. –  slm May 10 '13 at 15:44
    
1<> is Bourne read-write redirection, one of the standard redirection operators like < and >. –  Stephane Chazelas May 10 '13 at 16:48
    
Thanks, I found it in the man page after I asked. Learned something new today. Never noticed that method. –  slm May 10 '13 at 16:49
add comment

Your Answer

 
discard

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