bash sort通过数字键引用csv文件

问题描述 投票:4回答:5

我有以下输入csv文件:

"aaa","1","xxx"
"ccc, Inc.","6100","yyy"
"bbb","609","zzz"

我希望按第二列排序作为数字,我试过了

sort --field-separator=',' --key=2n

问题是,由于引用了所有值,因此它们无法通过-n(数字)选项正确排序。有解决方案吗?

bash sorting csv
5个回答
4
投票

一个小技巧,它使用双引号作为分隔符:

sort --field-separator='"' --key=4 -n

2
投票

对于引用的csv,请使用具有适当csv解析器的语言。以下是使用perl的示例。

perl -MText::ParseWords -lne '
    chomp; 
    push @line, [ parse_line(",", 0, $_) ];
}{ 
    @line = sort { $a->[1] <=> $b->[1] } @line;
    for (@line) {
        local $" = qw(",");
        print qq("@$_");
    }
' file

输出:

"aaa","1","xxx"
"bbb","609","zzz"
"ccc, Inc.","6100","yyy"

说明:

  • 使用chomp函数从输入中删除新行。
  • 使用代码模块Text::Parsewords解析引用的行并将其存储在没有引号的数组数组中。
  • END块中,对第二列上的数组数组进行排序,并将其分配给原始数组数组。
  • 对于数组数组中的每个项目,我们将输出列表分隔符设置为",",然后使用前面和后面的"打印它以创建原始格式的行。

2
投票

将您的示例放入名为sort2.txt的文件中我发现以下内容可以正常工作。 sort -t'"' -k4n sort2.txt使用以下命令排序(感谢Jonathan的改进)

  • -t [选项卡以外的可选单字符分隔符。在单引号中定义''''。
  • -k4选择第四个键中的值。(k)用“,”和第四个键值分隔
  • -n数字排序
  • 文件名避免使用链接作为不必要的
  • 希望这可以帮助!


    0
    投票

    没有一个非常简单的解决方案。如果你做出一些合理的假设,那么你可以考虑:

    sed 's/","/^A/g' input.csv |
    sort -t'^A' -k 2n |
    sed 's/^A/","/g
    

    这将","序列替换为Control-A(在代码中显示为^A),然后将其用作sort中的字段分隔符(第2列上的数字排序),然后再次使用","替换Control-A字符。

    如果你使用bash,你可以使用ANSI C quoting机制$'\1'将控制字符可视地嵌入到脚本中;你只需要在转义之前完成单引号字符串,然后重启它:

    sed 's/","/'$'\1''/g' input.csv |
    sort -t$'^A' -k 2n |
    sed 's/'$'\1''/","/g
    

    或者使用双引号而不是单引号,但由于您要替换的双引号,这会变得混乱。但你可以简单地逐字输入字符,像vim这样的编辑会乐意向你展示。


    0
    投票

    有时,只有在必要时才会引用CSV文件中的值。在这种情况下,使用"作为分隔符是不可靠的。

    例:

    "Forest fruits",198
    Apples,456
    bananas,67
    

    使用awksortcut,您可以在第一列中对原始文件进行排序:

    awk -F',' '{
        a = $1; # or the column index you want
        gsub(/(^"|"$)/, "", a);
        print a","$0
    }' file.csv | sort -k1 | cut -d',' -f1 --complement
    

    这将使您想要在前面排序的列没有引号,然后按照您想要的方式对其进行排序,并在最后删除此列。

    © www.soinside.com 2019 - 2024. All rights reserved.