Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort rows in csv file without header & first column

Tags:

sed

awk

I've a CSV file containing records like below.

   id,h1,h2,h3,h4,h5,h6,h7 
   101,zebra,1,papa,4,dog,3,apple
   102,2,yahoo,5,kangaroo,7,ape

I want to sort rows into this file without header and first column. My output should like this.

  id,h1,h2,h3,h4,h5,h6,h7
  101,1,3,4,apple,dog,papa,zebra
  102,2,5,7,ape,kangaroo,yahoo

I tried below AWK but don't know how to exclude header and first column.

awk -F"," ' {
s=""
for(i=1; i<=NF; i++) { a[i]=$i; }
for(i=1; i<=NF; i++)
{
for(j = i+1; j<=NF; j++)
{
if (a[i] >= a[j])
{
temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
for(i=1; i<=NF; i++){ s = s","a[i]; }
print s
} 
' file

Thanks

like image 697
Priyanka Avatar asked Feb 22 '18 06:02

Priyanka


2 Answers

If perl is okay:

$ perl -F, -lane 'print join ",", $.==1 ? @F : ($F[0], sort @F[1..$#F])' ip.txt
id,h1,h2,h3,h4,h5,h6,h7 
101,1,3,4,apple,dog,papa,zebra
102,2,5,7,ape,kangaroo,yahoo
  • -F, to indicate , as input field separator, results saved in @F array
    • See https://perldoc.perl.org/perlrun#Command-Switches for details on other options
  • join "," to use , as output field separator
  • $.==1 ? @F for first line, print as is
  • ($F[0], sort @F[1..$#F]) for other lines, get first field and sorted output of other fields
    • .. is range operator, $#F will give index of last field
    • you can also use (shift @F, sort @F) instead of ($F[0], sort @F[1..$#F])

For given header, sorting first line would work too, so this can simplify logic required

$ # can also use: perl -F, -lane 'print join ",", shift @F, sort @F'
$ perl -F, -lane 'print join ",", $F[0], sort @F[1..$#F]' ip.txt
id,h1,h2,h3,h4,h5,h6,h7 
101,1,3,4,apple,dog,papa,zebra
102,2,5,7,ape,kangaroo,yahoo

$ # can also use: ruby -F, -lane 'print [$F.shift, $F.sort] * ","'
$ ruby -F, -lane 'print [$F[0], $F.drop(1).sort] * ","' ip.txt
id,h1,h2,h3,h4,h5,h6,h7 
101,1,3,4,apple,dog,papa,zebra
102,2,5,7,ape,kangaroo,yahoo
like image 79
Sundeep Avatar answered Oct 04 '22 22:10

Sundeep


if you have gawk use asort:

awk -v OFS="," 'NR>1{split($0, a, ",");
                $1=a[1];
                delete a[1];
                n = asort(a, b);
                for (i = 1; i <= n; i++){ $(i+1)=b[i]}};
                1' file.csv

This splits the columns to array a with seperator as , for all raws except the first one.

Then assign the first value in the column in a raw with the first value in a and delete this value from a.

Now the a is sorted to b and assign value starting from 2 column. then print it.

like image 28
jijinp Avatar answered Oct 05 '22 00:10

jijinp