Tom's Guide | Tom's Hardware | Tom's Games
![]() |
![]() |
![]() |
Hi, I have a file constructed as follows:
header , N1
1 Contents
1220 SPC
8 SSN
1 Contents
1221 SPC
8 SSN
1 Contents
1222 SPC
8 SSN
footer , N2The values preceeding contents and ssn never change. I have a sed command that inserts a new batch of three 3 rows (contents, spc, ssn) above the line that ends in N2. The problem is that the numbers preceeding SPC must be in ascending numerical order. Sometimes the spc value in the new batch is < the previous spc value giving me something like this:
header , N1
1 Contents
1220 SPC
8 SSN
1 Contents
1221 SPC
8 SSN
1 Contents
1222 SPC
8 SSN
1 Contents
1000 SPC
8 SSN
footer , N2I therefore want to sort in batches of 3 lines by spc which would give me this:
header , N1
1 Contents
1000 SPC
8 SSN
1 Contents
1220 SPC
8 SSN
1 Contents
1221 SPC
8 SSN
1 Contents
1222 SPC
8 SSN
footer , N2All is can achieve at the moment is:
header , N1
1 contents
1 contents
1 contents
1 contents
8 SSN
8 SSN
8 SSN
8 SSN
1000 SPC
1220 SPC
1221 SPC
1222 SPC
footer , N1Does anybody have any ideas how to sort it as I want, or alternatively place the new batch of three lines in the correct order to start with?
Much appreciated
Andrew Taylor

I see no way of solving this without breaking apart the data file. It's a kludge, but this appears to work:
1) remove the header and footer, first and last lines:
sed -e '$d' -e '1d' data.file > newdata.file2) In the directory where data.file resides create a directory, mytmp, and split the newdata.file into files with 3 lines:
split -l 3 newdata.file mytmp/x
3) rename all the files in the mytmp directory to the 'number preceding SPC'
#!/bin/ksh
find mytmp -type f |while read fname
do
mv $fname mytmp/$(sed -n '2p' $fname|awk ' { print $1 } ')
done4) By default, the ls command sorts alphabetically so you can put the file back together with this:
#!/bin/ksh
ls -1 mytmp|while read ffile
do
cat mytmp/$ffile >> myfile
done
# end scriptI'll leave it to you to put the header and footer back into myfile.
Finally, the above should work provided your numbers are four characters. If the number is NOT four characters you'll have to do something like this and sort numerically:
# untested
ls -1 mytmp|sort -n |while read ffile
.
.

This awk solution outputs each set of 3 lines preceded by the desired sort field, which I have allowed to be as large as 6 digits. After sorting, the prepended sort field is taken off with the cut command. It assumes that the first line is a header line, but you could easily add an if-statement to confirm that.
awk 'BEGIN \
{getline
printf " %s\n",$0}
{if ($1!="footer")
{l1=$0
getline
sortkey=$1
l2=$0
getline l3
printf "%6.6d %s\n",sortkey,l1
printf "%6.6d %s\n",sortkey,l2
printf "%6.6d %s\n",sortkey,l3
}
else
printf "zzzzzz %s\n",$0
}
' file.in |
sort -k1,1 -k3,3n |
cut -c-8- > file.outBelow is the direct output from awk prior to being piped into sort:
header , N1
001220 1 Contents
001220 1220 SPC
001220 8 SSN
001221 1 Contents
001221 1221 SPC
001221 8 SSN
001222 1 Contents
001222 1222 SPC
001222 8 SSN
001000 1 Contents
001000 1000 SPC
001000 8 SSN
zzzzzz footer , N2

![]() |
![]() |
![]() |

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.
| Ads by Google |