【问题标题】:Look behind regex in one-liner perl在单行 perl 中查看正则表达式
【发布时间】:2019-04-21 23:33:08
【问题描述】:

我正在尝试制作一个当github落后于golang 时打印的单行脚本。

例如,java is a language used in github 应该匹配,但 golang is a language used in github 不应该匹配。

我试过/(?<!golang).*github/这个表达式,但它不起作用。

echo "golang is a language used in github" |
    perl -nle'print /(?<!golang).*github/ ? "match" : "no match"'

这将打印match 而不是no match

如何在 Perl 中使用“消极的后视”来做到这一点?

(使用 Perl v5.28.1)

【问题讨论】:

  • 在您的示例中,模式在位置 0 匹配。位置 0 不是紧跟在 golang 之前,它是匹配 .*github 的字符串的开头
  • 是否需要匹配"java is a language used in github, but golang is not"(github precedes golang)?

标签: perl regex-negation regex-lookarounds


【解决方案1】:

您的表达式匹配其中包含单词“github”的所有字符串。让我们看看为什么:

/(?<!golang).*github/

只要 Perl 可以调整 .* 以匹配足够的字符,就不会遇到紧接在 golang 前面的情况。正则表达式是贪婪的,.* 将尽可能多地匹配,同时仍然保持模式匹配的其余部分。

所以如果你的字符串是

golang is a language used in github

正则表达式可以通过将字符串分配给不同的部分来匹配:

  • (?&lt;!golang) 匹配字符串的开头
  • .* 得到“golang is a language used in
  • github 得到“github

实现您想要的一种可能成本高昂的方法是:

/^(?:(?!golang).)*github/

它的工作原理是确保“github”之前的所有字符都不以序列“golang”开头。

所以

echo "java is a language used in github" | perl -ne 'print q!Not golang: !, /^(?:(?!golang).)*github/ ? q!true! : q!false!'

将打印出Not golang: true

echo "golang is a language used in github" | perl -ne 'print q!Not golang: !, /^(?:(?!golang).)*github/ ? q!true! : q!false!'

将打印出Not golang: false


另一种(不那么混淆的)方法是进行两次连续测试:

/^(.*)github/  and  $1 !~ /golang/

如果您正在执行数万或数十万行,也许测试两种方法以找出哪个更快?

【讨论】:

    【解决方案2】:

    改善波西米亚风格,

    /^(?!.*golang.*github).*github/
    

    【讨论】:

      【解决方案3】:

      只需使用锚定的负面展望来开始:

      ^(?!.*golang).*github
      

      【讨论】:

      • 这将错误地无法匹配github golang
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-07
      • 1970-01-01
      相关资源
      最近更新 更多