Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash - sort range of lines in file

Hi fellow overflow users.

I would love to know how to sort a range of lines in a file through a terminal command in Linux.

For example in a test.sh file:

g++ -o test.out \
Main.cpp \
Framework.cpp \
Sample.cpp \
Blub.cpp \
-std=c++14 -lboost

How do I sort from the second line to the second last line (the source file names) in this file.

Desired Output:

g++ -o test.out \
Blub.cpp \
Framework.cpp \
Main.cpp \
Sample.cpp \
-std=c++14 -lboost

(Sorted from line 2 - 5)

Thank you for your attention :)

like image 674
DasOhmoff San Avatar asked Sep 01 '25 18:09

DasOhmoff San


2 Answers

Sorting using the ex line editor:

$ cat file
g++ -o test.out \
Sample.cpp \
Main.cpp \
Framework.cpp \
Blub.cpp \
-std=c++14 -lboost

$ echo 'x' | ex -s -c '2,5!sort' file

$ cat file
g++ -o test.out \
Blub.cpp \
Framework.cpp \
Main.cpp \
Sample.cpp \
-std=c++14 -lboost

ex -s -c '2,5!sort' will put ex in batch mode (with -s) and apply the command 2,5!sort to the input file. This will sort lines 2 through 5 by executing the external sort utility with the lines in the given range and then replacing the same lines with the output of sort.

The echo 'x' is used to send the x command to ex which will make it save its modified buffer and exit. Without this, you would have had to manually type x at the terminal and press Enter to exit ex.

This assumes classic ex (as found in BSD). If you have ex from a Vim distribution, you may use

$ ex -s -c '2,5 sort|x' file

This uses the internal sort command in Vim's ex (same as :sort in Vim).


As requested in comments:

To sort all lines from line 2 down to the second to last line in the file using BSD ex:

$ echo 'x' | ex -s -c '2,$-1!sort' file

or, with Vim's ex:

$ ex -s -c '2,$-1 sort|x' file

The range was change from 2,5 to 2,$-1, i.e., from line 2 to "the end minus one".


It's a pity that sed doesn't support the same type of operation.

like image 134
Kusalananda Avatar answered Sep 04 '25 07:09

Kusalananda


With head, GNU sed and tail:

(head -n 1 test.sh; sed -n '2,${/\\/p}' test.sh | sort; tail -n 1 test.sh) > test_new.sh

Output:

g++ -o test.out \
Blub.cpp \
Framework.cpp \
Main.cpp \
Sample.cpp \
-std=c++14 -lboost
like image 38
Cyrus Avatar answered Sep 04 '25 07:09

Cyrus