How can i sort by multiple field in terminal? - sorting

I'm looking for way to sort my list(CIDR notation of ip addresses) with linux terminal. My input list seems like this:
1.0.0.0/24
1.0.4.0/22
1.0.16.0/24
1.0.64.0/18
1.0.128.0/17
1.1.1.0/24
1.1.8.0/24
1.1.20.0/24
1.1.64.0/19
1.1.103.0/24
1.1.104.0/21
1.1.112.0/20
1.1.128.0/17
1.2.4.0/24
1.2.11.0/24
1.2.128.0/17
1.3.33.0/24
1.3.34.0/24
1.3.101.0/24
1.4.128.0/17
1.5.0.0/16
1.6.0.0/17
1.6.128.0/18
1.8.18.0/24
1.9.0.0/16
1.10.72.0/23
1.10.128.0/17
1.11.0.0/16
1.16.0.0/18
1.18.116.0/22
I use sort command of terminal but can't sort that like what i want (First i want to sort by prefix then by IP address ). After using sort command:
$ sort -t '/' -k 2,2n -k1,1n input > output
Output after sort command:
180.0.0.0/10
183.0.0.0/10
183.192.0.0/10
196.64.0.0/10
208.192.0.0/10
219.0.0.0/10
220.0.0.0/10
221.0.0.0/10
221.192.0.0/10
222.0.0.0/10
223.64.0.0/10
1.128.0.0/11
1.224.0.0/11
2.0.0.0/11
2.96.0.0/11
8.224.0.0/11
13.64.0.0/11
14.32.0.0/11
14.64.0.0/11
20.0.0.0/11
23.192.0.0/11 <---
23.32.0.0/11 <---
27.160.0.0/11
27.192.0.0/11
27.64.0.0/11
31.224.0.0/11
35.160.0.0/11
35.224.0.0/11
36.192.0.0/11
37.160.0.0/11
39.32.0.0/11
39.64.0.0/11
The problem is that is sort just by first octet. Any help or better way to solve it?

i solve it like this. First change slash(/) to dot(.) then sort my list and reverse swapping from the last dot(.) to slash(/) to have output like my origin file.
Swap / to . with sed command:
sed -e 's/\//./g' input > output
Sort list by multiple field with sort command:
sort -t '.' -k 5,5n -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k1,1n output > output_sorted
and at last change last dot(.) to slash:
sed 's/\./\//4' output_sorted > origin_sorted_file

With sort from GNU coreutils version 6.10 and newer(*) you can just use something like
sort -t '.' -k 1,1n -k 2,2n -k 3,3n -k 4,4n input > output
The sort command will just ignore trailing characters in a field not being part of a number.
(*) note: 6.10 (from 2008) was just the oldest version of sort / coreutils I had access to.

Related

Sorting multiple columns in ascending order

Source:
10,10,7.17,1.077383,0.00428382
10,12,7.45,1.177068,0.00390197
10,4,6.86,1.184806,0.00489828
10,6,6.98,1.106846,0.00463645
10,8,7.09,1.106254,0.00451672
12,10,6.71,1.224453,0.00506310
12,12,6.96,1.141856,0.00446641
12,4,6.41,1.510563,0.00590838
12,6,6.51,1.187841,0.00548915
12,8,6.62,1.217152,0.00532222
Desired result
10,4,6.86,1.184806,0.00489828
10,6,6.98,1.106846,0.00463645
10,8,7.09,1.106254,0.00451672
10,10,7.17,1.077383,0.00428382
10,12,7.45,1.177068,0.00390197
12,4,6.41,1.510563,0.00590838
12,6,6.51,1.187841,0.00548915
12,8,6.62,1.217152,0.00532222
12,10,6.71,1.224453,0.00506310
12,12,6.96,1.141856,0.00446641
How do i sort the csv for the first two column such i get the desired result in ascending order.
10,4
10,6
10,8
10,12
sort -k1,2 -n -t, didn't work as expected
10,4,6.86,1.184806,0.00489828
10,6,6.98,1.106846,0.00463645
10,8,7.09,1.106254,0.00451672
12,4,6.41,1.510563,0.00590838
12,6,6.51,1.187841,0.00548915
12,8,6.62,1.217152,0.00532222
You can see that 10,10,7.17,1.077383,0.00428382 is missing
sort -k1,1 -k2,2 -n -t, worked fine
More info : https://unix.stackexchange.com/questions/78925/how-to-sort-by-multiple-columns
To answer your question you should use this:
sort -t, -k1,1n -k2,2n yourFile.csv
The problem with your command is that -n does no apply to the fields you try to sort on; -k1,2n would do that but it sill does not solves your problem because it will consider both fields together (e.g. 10,10, 10,12) and will not work probably because of the you locale.
If you try
LC_ALL=C sort -t, -k1,2n yourFile.csv
you will get something like:
10,10,7.17,1.077383,0.00428382
10,12,7.45,1.177068,0.00390197
10,4,6.86,1.184806,0.00489828
10,6,6.98,1.106846,0.00463645
10,8,7.09,1.106254,0.00451672
12,10,6.71,1.224453,0.00506310
12,12,6.96,1.141856,0.00446641
12,4,6.41,1.510563,0.00590838
12,6,6.51,1.187841,0.00548915
12,8,6.62,1.217152,0.00532222
(ordered by first two fields 'concatenated').

Sort lines by group and column

I have a csv file separated by semicolons. Which contains lines as shown below.. And I need to sort it by the first and third column, respecting the groups of lines defined by the value of the first column.
booke;book;2
booke;booke;1
booke;bookede;6
booke;bookedes;8
booke;booker;4
booke;bookes;7
booke;booket;3
booking;booking;1
booking;bookingen;2
booking;bookingens;3
booking;bookinger;7
booking;bookingerne;5
booking;bookingernes;6
booking;bookingers;8
booking;bookings;4
Expected output:
booke;booke;1
booke;book;2
booke;booket;3
booke;booker;4
booke;bookede;6
booke;bookes;7
booke;bookedes;8
booking;booking;1
booking;bookingen;2
booking;bookingens;3
booking;bookings;4
booking;bookingerne;5
booking;bookingernes;6
booking;bookinger;7
booking;bookingers;8
I tried it with sort -t; -k3,3n -k1,1 but it's sorted by the third entire column.
What about using two sorts in a pipeline fashion:
sort -t ';' -k 3,3n | sort -t ';' -k 1,1 -s
The -s in the second parameter is necessary in order to enable stable sort. Otherwise it could destroy the previous (third column) sorting.
EDIT: however as #BenjaminW. points out in his comment, you can use multiple -k flags, you only specified them the wrong way. By performing a sort:
sort -t ';' -k 1,1 -k 3,3n
It takes the first column als primary sorting column and the third as secondary.

How can I sort alphabetically and numerically in bash?

Right now I have a file as follows:
hostname=myhost1
id[12]=id12
id[3]=id3
id[2]=id2
id[7]=id7
alpha=a
Using sort in bash, how can I order my file as follows:
alpha=a
hostname=myhost1
id[2]=id2
id[3]=id3
id[7]=id7
id[12]=id12
I'm almost there... I get id[12]=id12 before all of the other id's.
Any help would be greatly appreciated
You can use:
sort -t '[' -nk2 file
alpha=a
hostname=myhost1
id[2]=id2
id[3]=id3
id[7]=id7
id[12]=id12
-t will set field separator as [ and -nk2 will sort the input numerically by field 2 wherever [ is found.
I was able to resolve the issue with the following sort command:
sort -t '[' -k 1,1 -k 2,2n filename

Unix sort command with blank value

I am using below sort command to sort 2 fields in desc order and there is a chance that the second field can be blank in some cases.
sort -k 1.1,1.2n -brn -k 1.5,1.6 -o
sample data:
112321
112422
112526
1124
112623
output must be as below
1124
112526
112623
112422
112321
Can you please help me out with a solution, thanks!!!!
Do it as two separate commands and concatenate the results.
{ grep -v '^.....' input | sort -k 1.1,1.2n;
grep '^.....' input | sort -k 1.1,1.2n -brn -k 1.5,1.6; } > output

Bash and sort files in order

with a previous bash script I created a list of files:
data_1_box
data_2_box
...
data_10_box
...
data_99_box
the thing is that now I need to concatenate them, so I tried
ls -l data_*
but I get
.....
data_89_box
data_8_box
data_90_box
...
data_99_box
data_9_box
but I need to get in the sucession 1, 2, 3, 4, .. 9, ..., 89, 90, 91, ..., 99
Can it be done in bash?
ls data_* | sort -n -t _ -k 2
-n: sorts numerically
-t: field separator '_'
-k: sort on second field, in your case the numbers after the first '_'
How about using the -v flag to ls? The purpose of the flag is to sort files according to version number, but it works just as well here and eliminates the need to pipe the result to sort:
ls -lv data_*
If your sort has version sort, try:
ls -1 | sort -V
(that's a capital V).
This is a generic answer! You have to apply rules to the specific set of data
ls | sort
Example:
ls | sort -n -t _ -k 2
maybe you'll like SistemaNumeri.py ("fix numbers"): it renames your
data_1_box
data_2_box
...
data_10_box
...
data_99_box
in
data_01_box
data_02_box
...
data_10_box
...
data_99_box
Here's the way to do it in bash if your sort doesn't have version sort:
cat <your_former_ls_output_file> | awk ' BEGIN { FS="_" } { printf( "%03d\n",$2) }' | sort | awk ' { printf( "data_%d_box\n", $1) }'
All in one line. Keep in mind, I haven't tested this on your specific data, so it might need a little tweaking to work correctly for you. This outlines a good, robust and relatively simple solution, though. Of course, you can always swap the cat+filename in the beginning with an the actual ls to create the file data on the fly. For capturing the actual filename column, you can choose between correct ls parameters or piping through either cut or awk.
One suggestion I can think of is this :
for i in `seq 1 5`
do
cat "data_${i}_box"
done
I have files in a folder and need to sort them based on the number. E.g. -
abc_dr-1.txt
hg_io-5.txt
kls_er_we-3.txt
sd-4.txt
sl_rt_we_yh-2.txt
I need to sort them based on number.
So I used this to sort.
ls -1 | sort -t '-' -nk2

Resources