【问题标题】:awk extract multiple groups from each lineawk 从每一行中提取多个组
【发布时间】:2010-11-10 02:43:12
【问题描述】:

当模式在一行中多次匹配时,如何对所有匹配组执行操作?

为了说明,我想搜索/Hello! (\d+)/并使用数字,例如,将它们打印出来或将它们相加,以便输入

abcHello! 200 300 Hello! Hello! 400z3
ads
Hello! 0

如果我决定将它们打印出来,我希望输出

200
400
0

【问题讨论】:

  • 对于 Google 员工:请注意,gawk,又名。 “GNU awk”,您实际上可以在一行(例如通过管道)中执行标题所说的(不是问题):| gawk -v RS='' '{ print gensub(/()()/, "\\1\\2", "g"); }' :D 这支持多行(由于-v RS='')和匹配的子-组(由于使用 gawk 的gensub)!!!

标签: regex awk grouping


【解决方案1】:

GNU awk

awk 'BEGIN{ RS="Hello! ";}
{
    gsub(/[^0-9].*/,"",$1)
    if ($1 != ""){ 
        print $1 
    }
}' file

【讨论】:

  • 不错,但不适用于更复杂的模式,例如 /([a-g]+|[h-z]+)/ 并且会匹配换行符。
【解决方案2】:

这是gawk 语法。当没有固定文本可以用作记录分隔符并且与换行符不匹配时,它也适用于模式:

 {
     pattern = "([a-g]+|[h-z]+)"
     while (match($0, pattern, arr))
     {
         val = arr[1]
         print val
         sub(pattern, "")
     }
 }

【讨论】:

  • 最后的sub 有很大的不同!可悲的是,我花了一些时间来尝试...谢谢!
【解决方案3】:

这是一个简单的语法,每个 awk(nawk、mawk、gawk 等)都可以使用它。

{
    while (match($0, /Hello! [0-9]+/)) {
        pattern = substr($0, RSTART, RLENGTH);
        sub(/Hello! /, "", pattern);
        print pattern;
        $0 = substr($0, RSTART + RLENGTH);
    }
}

【讨论】:

    【解决方案4】:

    没有 gawk 函数可以在一行中多次匹配相同的模式。除非您确切知道该模式重复了多少次。

    有了这个,您必须“手动”迭代同一行中的所有匹配项。对于您的示例输入,它将是:

    {
      from = 0
      pos = match( $0, /Hello! ([0-9]+)/, val )
      while( 0 < pos )
      {
        print val[1]
        from += pos + val[0, "length"]
        pos = match( substr( $0, from ), /Hello! ([0-9]+)/, val )
      }
    }
    

    如果模式应该在换行符上匹配,您必须修改输入记录分隔符 - RS

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多