对没有标题和第一列的csv文件中的行进行排序

Posted

技术标签:

【中文标题】对没有标题和第一列的csv文件中的行进行排序【英文标题】:Sort rows in csv file without header & first column 【发布时间】:2018-08-01 21:40:00 【问题描述】:

我有一个包含如下记录的 CSV 文件。

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

我想将行排序到这个文件中,没有标题和第一列。我的输出应该是这样的。

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

我在 AWK 下试过,但不知道如何排除标题和第一列。

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

谢谢

【问题讨论】:

为什么你的代码没有缩进? 【参考方案1】:

如果perl 没问题:

$ 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, 表示, 作为输入字段分隔符,结果保存在@F 数组中 有关其他选项的详细信息,请参阅 https://perldoc.perl.org/perlrun#Command-Switches join "," 使用 , 作为输出字段分隔符 $.==1 ? @F 第一行,按原样打印 ($F[0], sort @F[1..$#F]) 对于其他行,获取第一个字段和其他字段的排序输出 .. 是范围运算符,$#F 将给出最后一个字段的索引 您也可以使用(shift @F, sort @F) 代替($F[0], sort @F[1..$#F])

对于给定的标题,排序第一行也可以,所以这可以简化所需的逻辑

$ # 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

【讨论】:

perl 摇滚!!你也是! 我刚从your 2nd perl one-liners article 来到这里,说如果您安装了其中一个模块,您可以使用Sort::Versions 或Sort::Naturally 模块进行自然排序。例如perl -MSort::Naturally -F, -lane 'print join ",", $.==1 ? @F : (shift @F, nsort @F)' ip.txt @cas 谢谢,我最近用过version,也会去看看Sort::Naturally【参考方案2】:

如果您有gawk,请使用asort

awk -v OFS="," 'NR>1split($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

这会将列拆分为数组a,分隔符为,,用于除第一个以外的所有原始数据。

然后将原始列中的第一个值与a 中的第一个值一起分配,并从a 中删除该值。

现在a 被排序为b 并从2 列开始赋值。然后打印它。

【讨论】:

【参考方案3】:

您可以根据您的要求使用awk 中的asort() 函数,然后从第二行开始对它们进行排序。解决方案是 GNU awk 特定的,因为 length(array) 函数

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

我们的想法是,首先我们用, 分隔符将整行拆分为数组a,从中我们将第二个字段中的元素从新数组b 中取出。我们对这个新数组中的这些元素进行排序,并在最终打印时附加第一个列元素。

【讨论】:

以上是关于对没有标题和第一列的csv文件中的行进行排序的主要内容,如果未能解决你的问题,请参考以下文章

将python字典写入CSV列:第一列的键,第二列的值

python如何根据csv中一列的内容对另一列进行写入

按数值排序 csv

根据第一列对 CSV 文件进行排序

求助,python如何在csv插入一列的问题

如何在数据工厂中获取 CSV 的第一行和第一列值?