【问题标题】:Regex with awk or gawk带有 awk 或 gawk 的正则表达式
【发布时间】:2013-02-07 21:59:35
【问题描述】:

我是 awk/gawk 的初学者。 如果我在下面运行,shell 什么也没给我。请帮忙!

echo "A=1,B=2,3,C=,D=5,6,E=7,8,9"|awk 'BEGIN{
n = split($0, arr, /,(?=\\w+=)/)
for (x=1; x<n; x++) printf "arr[%d]=%s\n", x, arr[x]
}'

.................................................. ......

我正在尝试解析:

A=1,B=2,3,C=,D=5,6,E=7,8,9

预期输出:

A=1
B=2,3
C=
D=5,6
E=7,8,9

我敢打赌我的 awk 有问题。

【问题讨论】:

  • 在 awk 中没有前瞻,IIRC。
  • 自记录测试用例的好问题。继续发帖,祝你好运!

标签: regex awk gawk


【解决方案1】:

gawk 支持前瞻。

如果您希望 gawk 按预期解析它,请尝试以下操作:

awk '{n=split(gensub(/,([A-Z])/, " \\1","g" ),arr," ");for(x=1;x<=n;x++)print arr[x]}'

用你的例子测试:

kent$  echo "A=1,B=2,3,C=,D=5,6,E=7,8,9"|awk '{n=split(gensub(/,([A-Z])/, " \\1","g" ),arr," ");for(x=1;x<=n;x++)print arr[x]}'
A=1
B=2,3
C=
D=5,6
E=7,8,9

【讨论】:

  • 哦,我喜欢这样。我试图弄清楚如何拆分,但我没有想到使用gensub() 并使用反向引用来保留我们想要保留的部分。 +1。
  • @steveha 谢谢。第一个出现的是sed -r 's/,([A-Z])/ \1/g'|awk 'simple split..',但我认为在单个进程中编写会很好。
【解决方案2】:

使用 sed 可能会更容易:

$ echo "A=1,B=2,3,C=,D=5,6,E=7,8,9" | sed 's/,\(\w\+=\)/\n\1/g'
A=1
B=2,3
C=
D=5,6
E=7,8,9

【讨论】:

    【解决方案3】:

    如果你使用 gnu awk,你可以这样做:

    awk '{printf $0 "\n" substr( RT, 2 )}' RS=,[A-Z]
    

    【讨论】:

    • 我也在考虑使用 RS,但不知道如何使用 RT 获取该 macthed 文本 :)
    【解决方案4】:

    作为 nhahtdh,在 awk 中没有前瞻...但是您可以为分配使用不同的分隔符。为什么不是“A=1;B=2,3,4;C=5...”? 如果您的输入必须具有该格式,请尝试使用 flex...

    【讨论】:

      【解决方案5】:

      您也可以使用逗号作为记录分隔符:

      echo "A=1,B=2,3,C=,D=5,6,E=7,8,9" |
      awk -v RS=, '{sep=","} /=/ {sep="\n"} NR==1 {sep=""} {printf "%s%s", sep, $0}'
      

      输出

      A=1
      B=2,3
      C=
      D=5,6
      E=7,8,9
      

      【讨论】:

        【解决方案6】:

        你有两个问题。首先,您不需要BEGIN 子句;您只希望它在每个输入行上运行。其次,您正在尝试使用 AWK 不支持的正则表达式功能。

        不要尝试使用拆分字符串的花哨模式,而是循环并调用match() 来解析出您想要的功能。

        echo "A=1,B=2,3,C=,D=5,6,E=7,8,9"|awk '
        {
            line = $0
            for (i = 0;;)
            {
                i = match(line, /([A-Z]+)=([0-9,]*)(,|$)/, arr)
                if (0 == i)
                    break
                key = arr[1]
                value = arr[2]
                l = length(key "=" value ",") + 1
                line = substr(line, l)
                printf "DEBUG: key '%s' value '%s'\n", key, value
            }
        }'
        

        打印出来:

        DEBUG: key A value 1
        DEBUG: key B value 2,3
        DEBUG: key C value
        DEBUG: key D value 5,6
        DEBUG: key E value 7,8,9
        

        【讨论】:

          【解决方案7】:

          使用 awk 的其他方式

          awk '{print gensub(/,([A-Z]+=)/, "\n\\1","g")}' temp.txt
          

          输出

          A=1
          B=2,3
          C=
          D=5,6
          E=7,8,9
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-14
            • 2022-11-29
            相关资源
            最近更新 更多