【问题标题】:Sort numeric values except text in Bash对除 Bash 中的文本以外的数值进行排序
【发布时间】:2019-08-17 19:59:26
【问题描述】:

我有一个名为 prices.csv 的 csv 文件,如下所示:

Name, Price, Description
Apple, 2.85, fruit
Kiwi, 1.96, fruit
Banana, 0.99, fruit
Peach, Not available, fruit
Orange, 2.02, fruit

我想按升序对第二列(价格)进行排序,除了“不可用”的值,这些应该放在底部。

到目前为止,我所做的是:

sort -t, -k2,2 -n prices.csv > ordered_prices.csv

这将创建以下文件:

Name, Price, Description
Peach, Not available, fruit
Banana, 0.99, fruit
Kiwi, 1.96, fruit
Orange, 2.02, fruit
Apple, 2.85, fruit

如您所见,这会将价格为“不可用”的产品放在顶部而不是底部。如何使用通用代码将文本放在底部?

【问题讨论】:

    标签: bash sorting awk


    【解决方案1】:

    如果你有gnu-awk,那么你可以使用PROCINFO

    awk -F ', ' 'NR == 1 {
       print
       next
    }
    $2+0 == $2 {
       a[NR] = $2
       rec[NR] = $0
       next
    }
    {
       rest = rest $0 RS
    }
    END {
       PROCINFO["sorted_in"] = "@val_num_asc"
       for (i in a)
          print rec[i]
       printf "%s", rest
    }' file
    

    Name, Price, Description
    Banana, 0.99, fruit
    Kiwi, 1.96, fruit
    Orange, 2.02, fruit
    Apple, 2.85, fruit
    Peach, Not available, fruit
    

    您也可以像这样使用head + tail + sort 命令:

    head -n 1 file && sort -t, -k2V <(tail -n +2 file)
    

    【讨论】:

    • 嗨,您使用 awk 的第一个解决方案有效。我不知道你为什么删除它,但它是正确的解决方案。谢谢!
    • 不,我没有删除 awk 解决方案。只是将其格式化以使其更可红色。
    【解决方案2】:

    您可以考虑使用版本排序而不是数字排序:

    $ sort -t, -k2,2V  prices.csv > ordered_prices.csv
    

    更多关于版本排序的信息可以在here找到。请注意,这会将您的标题移到后面。你可以使用这个方法:

    $ OUTPUTFILE=outputfile
    $ awk -v out="$OUTPUTFILE" '(NR==1){print > out; close(out)}(NR>1)' inputfile \
      | sort -t, -k2,2V > $OUTPUTFILE
    

    但这太丑了,在这一点上我会改用 Anubhava 的解决方案。

    另一种方法是做一个荒谬的替换:

    $ sed '2,$s/\([[:alpha:]]\+\)/999999\1/g' | sort -t, -k2n | sed 's/999999//g'
    

    它使标题保持在适当的位置。

    【讨论】:

    • @anubhava 你是对的。我为它添加了一个丑陋的修复。
    猜你喜欢
    • 2017-04-12
    • 2021-10-28
    • 2017-07-08
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 2011-04-19
    相关资源
    最近更新 更多