正则表达式可在字符串中任何位置的语音标记之间获取字符串

时间:2019-06-04 17:04:43

标签: php regex

我正在一个项目中尝试在字符串中任何位置的两个语音标记之间提取字符串。除了一件事,它几乎可以工作。

让我说这行

"04\/06\/2019 17:56:45:\tTook 0 seconds to read lines for log 'Log Agent

这个想法我将进行两次正则表达式匹配,例如,对于一个没有感叹号的字符串,我将进行一次正则表达式搜索以匹配"Took 0 seconds",而另一次则寻找类似{ {1}}

我有以下正则表达式来查找不带感叹号开头的字符串。

!"Took 0 seconds"

但是上面的正则表达式仅在字符串前没有东西的情况下才与字符串匹配

例如如果搜索字符串是 $regex = '/[^.!](["\'])(?:(?=(\\\\?))\2.)*?\1/m'; $matches = null; preg_match_all($regex, $this->searchString, $matches, PREG_SET_ORDER, 0); 找不到

如果 "Took 0 seconds" 那么它会在正则表达式匹配项中正确找到字符串some other content "Took 0 seconds"

所以基本上我要问的是我该如何更改我的正则表达式,使得它可以从任何位置提取语音标记之间的字符串,即使它在开头也是如此。

更新

尝试并澄清我在做什么。我正在创建一个搜索解析器来查找数据库中的某些字符串。

在数据库中搜索将查找单个关键字(与容易解决的问题无关),并在数据库中查找特定的字符串。因此,如果我的搜索字符串为Took 0 seconds,则数据库将返回包含记录"took 0 seconds"的所有行。如果搜索字符串为took 0 seconds,那么我将能够检查数据库中是否不包含!"took 0 seconds"

如果我的搜索字符串是Took 0 seconds 那么正则表达式将返回keyword1 keyword2 "took 0 seconds" keyword 3

下面是一个regex101链接,提供了一些示例以及问题所在,您会注意到第一个链接本身只是“花了0秒”而没有被匹配。

1 个答案:

答案 0 :(得分:3)

正如@Toto在评论中指出的那样,您可以在后面使用负向后看,而不是匹配字符类中的字符。

您可能要做的是更新模式,使其仅使用第一个捕获组。当您使用模式或使用tempered greedy token解决方案时,该模式可能如下所示:

(?<![.!])(["'])(?:(?!\1).)*\1
  • (?<![.!])
  • (["'])在组1中捕获"'
  • (?:(?!\1).)*循环0+次与任何字符匹配,而右侧的字符不是组1
  • \1将反向引用匹配到组1

Regex demo

请注意,由于使用*量词,它也将与""

相匹配

获得这些匹配项的另一种方法可能是使用非贪婪匹配项.*?,然后使用第1组\1

(?<![.!])(["\']).*?\1

Regex demo