【问题标题】:Can grep print just the matched buffer?grep 可以只打印匹配的缓冲区吗?
【发布时间】:2016-12-25 09:53:55
【问题描述】:

如果我这样做

# perl -lne "print \$1 if /'?(\d{5})'?:/" courses.yaml
00000
01005

然后我得到了我想要的结果,但现在我想用grep 来代替。

为什么以下内容不能得到相同的输出?

# grep -oP "\'?(\d{5})\'?:" courses.yaml 
'00000':
'01005':

【问题讨论】:

  • 因为它返回与正则表达式匹配的所有内容。您可能想要使用\K 或一些前瞻/后视。
  • 您在第一种情况下打印第 1 组的内容,在第二种情况下打印整个匹配项。试试grep -oP "(\d{5})(?='?:)" courses.yaml
  • This answer 提供了有关使用前瞻/后瞻断言以使 -o 按您希望的方式工作的更多详细信息。
  • 为什么不坚持perl?或者更好的是,使用YAML 解析器,并且一开始就不要对其进行正则表达式?

标签: regex linux bash perl grep


【解决方案1】:

在第一种情况下打印第 1 组的内容,在第二种情况下打印整个匹配项。将grep-oP 一起使用时,您只能打印整个匹配项,因此,如果在: 后面有一个可选的单引号,则使用(?='?:) 前瞻只会返回一个5 位数的块:

echo "'00000':  '01005':" | grep -Po "\d{5}(?='?:)"

demo

我认为在这里使用lookbehind 没有意义,因为' 在您的模式中是可选的。

【讨论】:

    【解决方案2】:

    -o 是输出匹配项 ($&),而不是第一次捕获 ($1)。

    您可以使用\K、look-behinds 和/或look-aheads 来控制认为匹配的内容。

    在您的情况下,您可以使用以下内容:

    grep -oP "'?\K\d{5}(?='?:)" courses.yaml 
    

    但这简化为以下内容:

    grep -oP "\d{5}(?='?:)" courses.yaml 
    

    使用适当的 YAML 解析器会更有意义,而且仍然很短。

    【讨论】:

      猜你喜欢
      • 2014-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      相关资源
      最近更新 更多