对没有标题和第一列的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文件中的行进行排序的主要内容,如果未能解决你的问题,请参考以下文章