【问题标题】:Key, Value pair with multiples pairs on a line; sed键、值对,一行上有多个对; sed
【发布时间】:2014-11-09 14:38:05
【问题描述】:

假设我有一个文件在一行上有多个键值对:

$ cat test.txt
fruit: 23 oranges 55 bananas 3 peaches
candy: 16 m&m's 5 ju_ju_beans

使用 Perl,在每一行捕获多个未知数字的键、值对是很简单的:

$ perl -lane 'print "$1" while m/(\d+\s+\S+)/g' /tmp/test.txt
23 oranges
55 bananas
3 peaches
16 m&m's
5 ju_ju_beans

这可能与sed有关吗?

我试过了:

$ sed -E -n 's/(\d+\s+\S+)/$1\n/g; p' /tmp/test.txt
fruit: 23 oranges 55 bananas 3 peaches
candy: 16 m&m's 5 ju_ju_beans 

但这只是打印整行。是否有可能(在某些情况下,我的 Google foo 让我失望了)每行只打印一个键值对匹配?

【问题讨论】:

  • 我可以问一下——为什么要投反对票?这个问题有问题吗?老实说,我试着只问不明显的问题和有用的答案。欢迎反馈。
  • 已使用 regex 添加了 GNU awk 变体。

标签: bash perl sed


【解决方案1】:

grep 可以单独完成:

# perl compatible regex
grep -oP '\d+\s+\S+'
# vanilla basic regex
grep -o '[[:digit:]]\+[[:blank:]]\+[^[:blank:]]\+' file

【讨论】:

  • grep -oE '\d+\s+\S+' on OS X / BSD methinks
【解决方案2】:

sed 不识别 PCRE,并且使用 \1 而不是 $1 调用反向引用。话虽如此,您可以使用 GNU sed 尝试以下操作:

$ sed -r 's/([^[:digit:]]+)([[:digit:]]+[[:space:]]+[^[:space:]]+)/\2\n/g;' file
23 oranges
55 bananas
3 peaches

16 m&m's
5 ju_ju_beans

【讨论】:

    【解决方案3】:

    这是一个简单的awk

    awk '{for (i=2;i<=NF;i+=2) print $i,$(i+1)}' file
    23 oranges
    55 bananas
    3 peaches
    16 m&m's
    5 ju_ju_beans
    

    【讨论】:

    • +1 你刚刚打败了我! :) 我更喜欢这种方法,因为它避免使用正则表达式。
    • 依赖于字段的顺序,而不是 \d+\s\S+ 的特定正则表达式匹配。
    • @dawg 两种方式都能得到想要的结果。这与正则表达式匹配一样安全。
    • 我确实在寻找正则表达式。你知道如何在awk 中使用正则表达式来处理由正则表达式描述的一行上的多个键、值对吗?
    【解决方案4】:

    对于sed,我们可以从@jaypal 的sed '/^$/d' 的解决方案后删除空行。

    sed -r 's/([^[:digit:]]+)([[:digit:]]+[[:space:]]+[^[:space:]]+)/\2\n/g;' file  | sed '/^$/d'
    

    输出在这里。

    23 oranges
    55 bananas
    3 peaches
    16 m&m's
    5 ju_ju_beans
    

    【讨论】:

      【解决方案5】:

      regex 与 GNU awk 一起使用:

      gawk '{printf "%s", gensub(/([^[:digit:]]+)([[:digit:]]+[[:space:]]+[^[:space:]]+)/,"\\2\n","g")}' file
      23 oranges
      55 bananas
      3 peaches
      16 m&m's
      5 ju_ju_beans
      

      GNU awk 支持 \s,但不支持 \D\d

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 2019-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多