【问题标题】:PCRE Regex - How to return matches with multiline string looking for multiple strings in any orderPCRE Regex - 如何返回匹配多行字符串以任何顺序查找多个字符串
【发布时间】:2016-11-03 21:38:46
【问题描述】:

我需要使用与 Perl 兼容的正则表达式来匹配文件中多行出现的多个字符串。

匹配项需要以任意顺序出现(服务器 servernameA.company.com 后跟 servernameZ.company.com 后跟 servernameD.company.com 或三者的任意顺序组合)。 注意:所有匹配项都会出现在每行的开头。

在我对grep -P 的测试中,我什至无法对以任何顺序出现在新行上的简单字符串术语产生匹配(即使使用/s/m 修饰符)。从阅读中我很确定我需要一个前瞻断言,但即使在分析了正则表达式的每一位以确保它与我的场景相关之后,我使用的样本也没有为我产生匹配。

由于我需要在生产中支持这一点,我想要一个简单且相对直接的解释。

示例输入

irrelevant_directive = 0

# Comment
server servernameA.company.com iburst

additional_directive = yes

server servernameZ.company.com iburst
server servernameD.company.com iburst

# Additional Comment
final_directive = true

期待

当且仅当字符串“serverA.company.com”、“serverZ.company.com”和'serverD.company.com' 后跟 iburst。必须包含所有 3 个字符串。

最后,如果答案(或非常相似的答案形式)可以在 single 行上以任何顺序检查字符串,那将非常有帮助。例如,如果我有一个单行字符串:preauth param audit=true silent deny=5 severe=false unlock_time=1000 time=20ms,并且我想确保术语 deny=5time=20ms 以任意顺序出现并且匹配。

提前感谢您的帮助。

【问题讨论】:

  • 你说的是 PCRE 还是 Perl 程序?
  • 感谢您的快速回复并查看此内容。 PCRE 专门。我将使用带有grep -P 的命令。请刷新,因为我在我之前遗漏的正则表达式的预期输出上添加了一个新的简短部分。
  • 那么请不要使用 Perl 进行标记。我会删除标签。有一个成熟的程序可以解决这个问题,但是在一个正则表达式中做到这一点会很困难。

标签: pcre multiline lookahead negative-lookahead


【解决方案1】:

关于主要问题 [关于次要问题,请参阅 Casimir et Hippolyte answer](使用 x 修饰符):https://regex101.com/r/mkxcap/5

(?:
  (?<a>.*serverA\.company\.com\s+iburst.*)
 |(?<z>.*serverZ\.company\.com\s+iburst.*)
 |(?<d>.*serverD\.company\.com\s+iburst.*)
 |[^\n]*(?:\n|$)
)++
(?(a)(?(z)(?(d)(*ACCEPT))))(*SKIP)(*F)

比赛现在都在azd捕获组中。

这不是最有效的(每行回溯 3 次...),但主要的收获是使用捕获组注册匹配,然后检查它们是否被定义。

【讨论】:

  • 感谢您提供此信息。我将原始问题中的示例文本放入一个文件中,并针对它尝试了这个正则表达式,但它没有返回命中。 grep -P '(?:(?&lt;a&gt;.*serverA\.company\.com\s+iburst.*)|(?&lt;z&gt;.*serverZ\.company\.com\s+iburst.*)|(?&lt;d&gt;.*serverD\.company\.com\s+iburst.*)|[^\n]*(?:\n|$))++(?(a)(?(z)(?(d)(*ACCEPT))))(*SKIP)(*F)' testing 什么也不返回。这需要微调吗?如果我可以确保这 3 行总是紧挨着出现(而不是整个文件的某个地方),那会使正则表达式更易于编写吗?在此先感谢!
  • @KurtW grep -P 的问题是它逐行匹配。您无法将跨越多行的任何内容与grep -P 匹配。您需要在此处提供 PCRE 整个文件。 (引用 grep 的手册页:“从 FILE 中获取模式,每行一个。”)
【解决方案2】:

你不需要使用PCRE的功能,你可以简单地在ERE中编写:

grep -E '.*(\bdeny=5\b.*\btime=20ms\b|\btime=20ms\b.*\bdeny=5\b).*' file

PCRE 方法会有所不同:(不过你也可以使用之前的模式)

grep -P '^(?=.*\bdeny=5\b).*\btime=20ms\b.*' file

【讨论】:

  • 嗨卡西米尔!这实际上是你回答的我的次要问题。谢谢,这很有帮助,但是您有解决主要问题的方法(多行)吗?对不起,如果我让事情变得比必要的更混乱。单行正则表达式是一个奖励,我现在正在测试它!
  • 嗨,Casimir,我确认您对单行问题的解决方案非常有效!谢谢。当你有机会时,你能看看我的主要问题吗?抱歉将两个合二为一——我以后不会这样做了。
  • 赞成,因为这很有帮助。 bwoebi 解决了我的主要问题。感谢您的宝贵时间!
猜你喜欢
  • 2020-01-26
  • 1970-01-01
  • 2012-12-27
  • 2015-03-07
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
相关资源
最近更新 更多