用于匹配单词的正则表达式,除非前一行以单词结尾

Posted

技术标签:

【中文标题】用于匹配单词的正则表达式,除非前一行以单词结尾【英文标题】:Regex for matching a word, unless the previous line ends with a word 【发布时间】:2018-02-10 15:07:51 【问题描述】:

我有一个包含许多句子的文本,由换行符和任意空格分隔:

Some thing.
  Some other text.
 Some line.
   Some additional text.
Some stuff.
    Some additional text.
Some additional text.

我如何只匹配那些Some 字,其中上一行不以thingstuff 结尾?

对于上面的例子,我会匹配这些词:

Some thing.           
  Some other text.          <-- skip, previous line ends with "thing."
 [Some] line.
   [Some] additional text.  
[Some] stuff.
    Some additional text.   <-- skip, previous line ends with "stuff."
[Some] additional text.

我尝试了(?&lt;!thing\.|stuff\.)[\r\n\s]+Some,但我不知道如何在否定的lookbehind 中包含空格+换行符?我发现了一些使用\K 来允许“可变长度”匹配的示例,但我显然根本不明白\K 是如何匹配的,因为我无法匹配任何东西。

【问题讨论】:

一开始的Some呢? 【参考方案1】:

您可以使用 PCRE 动词 (*SKIP)(*F) 使已知的抹茶失败,并交替使用您的匹配:

(?:thing|stuff)\.\R\s*\w+(*SKIP)(*F)|\bSome\b

RegEx Demo

当上一行以thing.stuff. 结尾时,此处(?:thing|stuff)\.\R\s*.*(*SKIP)(*F) 将跳过匹配失败。在交替的右侧,我们将得到我们的匹配。

【讨论】:

【参考方案2】:

您可以使用带有非捕获组的“sacrificial match”来匹配您不想要的内容,然后允许在捕获组中匹配您想要的内容:

/(?:^\s*Some.*(?:thing\.|stuff\.)\s*^\s*Some)|(^\s*Some)/m

Demo

或者,如果您想要第一个和第四个(如 cmets 中所述,您的示例不一致...)

/(?:(?:thing\.|stuff\.)\s*Some)|(^\s*Some)/m

Demo

或者,跳过第一个 Some 并包括第四个:

/(?:(?:thing\.|stuff\.)\s*Some)|((?<=\n)\s*Some)/m

Demo

此方法适用于大多数正则表达式。

在这种情况下,向后看是一个问题,因为向后看需要固定宽度。您描述的\s* 不是固定宽度。

【讨论】:

以上是关于用于匹配单词的正则表达式,除非前一行以单词结尾的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式:如何匹配以括号“)”结尾的单词

C ++ 11正则表达式匹配一个不以句点结尾的完整单词?

正则表达式:匹配以“AM”结尾的单词(不区分大小写比较)[重复]

正则表达式总结

如何找到包含“a”并且以“d”结尾的单词? (重击正则表达式)

正则表达式 - 匹配整个字符串,除非 [重复]