对 CSV 文件的元素进行排序

对 CSV 文件的元素进行排序

我有一个 csv 文件,每行有 7 个数字,如下所示:

1083,20,28,42,23,10,43
1084,20,5,29,59,40,33
1085,39,50,21,12,40,55
1086,45,4,6,23,10,2
1087,36,46,28,32,3,20

我想保留第一个数字(第 1 列)并对第 2 至 7 列进行排序,使文件类似于

1083,10,20,23,28,42,43
1084,5,20,29,33,40,59
1085,12,21,39,40,50,55
1086,2,4,6,10,45,23
1087,3,20,28,32,36,46

我怎样才能用 或其他什么来做到这awk一点sed

谢谢

答案1

perl

perl -F, -lape '$_ = join ",", shift @F, sort {$a <=> $b} @F' < input.csv

使用 GNU awk

gawk -F, '
  {
    split($0, a)
    printf "%s", a[1]
    delete a[1]
    n = asort(a)
    for (i = 1; i <= n ; i++) printf "%s", FS a[i]
    print ""
  }' < input.csv

或者使用join.awk图书馆(感谢@WeijunZhou)

gawk -i join -F, -v OFS=, '
  {
    split($0, a)
    first = a[1]
    delete a[1]
    n = asort(a)
    print first, join(a, 1, n, OFS)
  }'

答案2

您面临的问题是您的文件带有 MAC 行结尾 (\r),而您运行的命令则假定为 Unix 行结尾 (\n)。

使用Perl

$ perl -l015 -F, -0015 -pae '$_ = join ",", shift @F, sort { $a <=> $b } @F' input.csv

选项:

  • -l设置ORS\r= 八进制 15。
  • -0设置RS\r= 八进制 15。
  • -p将按记录循环遍历您的 csv 文件。 RS 由选项\r设置从输入文件中分割记录-0
  • -F将在读取每个记录时将字段分隔符设置为逗号。
  • -a将在将每个记录读入字段并存储在 array 中时将其拆分@F
  • 注意:提供选项的顺序很重要。

因此,您将得到的输出也应具有 MAC 行结尾。这就是为什么您没有看到预期的输出,而是根据此处给出的所有解决方案,所有输出记录都被压缩成一行。

答案3

为了简单起见csv,无需引用,请尝试以下操作:

while IFS= read -r l; do
    col1=$(printf '%s' "$l" | cut -d, -f1)
    printf '%s,' "$col1"
    printf '%s' "$l" | cut -d, -f2- | grep -o "[0-9]*" | sort -n | paste -sd,
done < file

答案4

尝试使用以下 awk 和 sed 的方法组合

j=awk '{print NR}' filename | sort -nr| sed -n '1p'

for ((i=1;i<=$j;i++)); do k=`awk -F "," -v  i="$i" 'NR==i {print $1}' i.txt` ;echo $k;awk -F "," -v i="$i" 'NR==i {$1=" ";print $0}' i.txt| sed -r "s/^\s+//g"| perl -pne "s/ /\n/g"| sort -n| perl -pne "s/\n/ /g";echo " "| sed "s/.*/&\n/g";done|sed '/^$/d'| sed "N;s/\n/ /g"| sed "s/ /,/g"| sed "s/\,*$//g"

输出

1083,10,20,23,28,42,43
1084,5,20,29,33,40,59
1085,12,21,39,40,50,55
1086,2,4,6,10,23,45
1087,3,20,28,32,36,46

相关内容