# Sorting blocks of lines

I have a file that contains 4n lines. Here is an excerpt from it containing 8 lines

``````6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619
6117 16.5979
6118 19.4111
6115 8.88433
``````

What I want to do is sort a block, where each block consists of 4 lines based on the first column. The output for the excerpt should look as shown below.

``````6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433
6116 6.619
6117 16.5979
6118 19.4111
``````
-

Using a Bourne-like shell,

``````while read a ; do                                           # Try reading a line.
printf '%s\n%s\n%s\n%s\n' "\$a" "\$b" "\$c" "\$d" | sort -n # Sort them.
done < data
``````
-

You can get a clean solution with R. If the table above is in a file called "table.txt", then perform the following steps. The desired result will be in the file "tableout.txt".

``````> x = read.table("table.txt", col.names=c("a", "b"))
> x
a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2
> xord = x[with(x, order(index, a)), ]
> xord
a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)
``````
-

You could use to add an initial serial number that changes every four lines and use that as the primary sorting column

``````awk '{print int((NR-1)/4), \$0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '
``````
-
This worked thanks – Meenakshi Nov 11 '13 at 3:28

If this is a one off and you don't want to learn python, perl or awk, you can go with the basic `split` and `sort` commands.

First split the file in 4 line chunks with the `-l` option:

``````split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
sort -n -o \$fn \$fn
done
cat my_prefix_* > output_file
rm my_prefix_*
``````

The `sort -n` sorts by numerical value of the first column (999 before 1234). `-a 6` should take care of a file with 26^6*4 lines. `my_prefix_` should be something unique to the directory you work with.

-

You can do it with Perl:

``````perl -nle '
push @a,\$_;
unless(\$. % 4){
print join "\n",sort {\$a <=> \$b} @a; # Sort @a, and print its contents
@a = (); # Empty @a to start a new block
}
' your_file
``````

How this works

• `-n` --> run the code for each input line (and put the current line in `\$_`)
• `-l` --> append a newline to the output of any `print`
• `-e` --> execute the following string as Perl code
• Each line is appended to the array `@a`.
• `\$.` holds the current line number and unless that number is not congruent to zero modulo 4, then we keep working. If it is congruent to zero modulo 4, we have reached a line whose number is a multiple of 4 (the end of a block), in which case, we sort the entries in `@a` in ascending numerical order and print the entries in the sorted array joined by a newline to standard output.
-