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

时间:2014-07-11 00:49:18

标签: bash sorting csv

我有以下输入csv文件:

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

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

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

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

5 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

将您的示例放入名为sort2.txt的文件中我发现以下内容效果很好 sort -t'"' -k4n sort2.txt 使用sort和以下命令(感谢Jonathan的改进)

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

    答案 2 :(得分: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块中,对第二列上的数组数组进行排序,并将其分配给原始数组数组。
    • 对于数组数组中的每个项目,我们将输出列表分隔符设置为",",然后使用前面和尾随"打印它以创建原始格式的行。

    答案 3 :(得分: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等编辑就会很乐意向您展示。

    答案 4 :(得分: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
    

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