Sort rows in csv file without header and first column

I have a CSV file containing entries as shown 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 the lines in this file without a header and first column. My conclusion should be like.

  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

+5
source share
3 answers

If perl is ok:

 $ 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 a field separator, the results stored in the @F array
  • join "," use , as a separator of output fields
  • $.==1 ? @F $.==1 ? @F for the first line, print as is
  • ($F[0], sort @F[1..$#F]) for other lines, get the first field and sort the output of other fields
    • .. - range operator, $#F will give the index of the last field


Sorting the first line will also work for this header, so this can simplify the required logic.

 $ 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 $ 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 
+5
source

if you have gawk using 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 into an array a with a delimiter like , for all source files except the first.

Then assign the first value in the column to raw with the first value in a and remove that value from a .

Now a sorted by b and assigns a value starting from 2 columns. then print it.

+4
source

You can simply use the asort() function in awk for your requirement and start sorting them from the second line in the panel. The solution is GNU awk , specific due to the length(array) function

 awk 'NR==1{ print; next } NR>1 { finalStr="" arrayLength="" delete b split( $0, a, "," ) for( i = 2; i <= length(a); i++ ) b[arrayLength++] = a[i] asort( b ) for( i = 1; i <= arrayLength ; i++ ) finalStr = (finalStr)?(finalStr","b[i]):(b[i]) printf( "%s", a[1]","finalStr ) printf( "\n" ); }' file 

The idea is that first we split the entire string with a separator into an array a , from which we get the elements from the second field to a new array b . We sort these elements in this new array and add the first column element when we finally print it.

+2
source

Source: https://habr.com/ru/post/1275499/


All Articles