【问题标题】:Regex word boundaries and distance between matches正则表达式单词边界和匹配之间的距离
【发布时间】:2015-07-16 09:09:46
【问题描述】:

我希望能够使用正则表达式来查找某些文本中特定关键词的任何匹配项。

关键词可能包含也可能不包含 1 个或多个空格(通常只有 1 个单词,但在某些情况下可能包含多个单词)。

我目前正在使用以下表达式,其中关键字是单个单词(不包含空格):

var regexPattern = string.Format( "\\b({0})\\b", keyphrase );

当关键字是多个单词(包含一个或多个空格)时,我会更新表达式以用通配符替换其中的任何空格:

regexPattern = regexPattern.Replace( " ", ".*" );

在某些情况下,它的行为并不符合我的需要。

1) 如果我的长文本(我正在搜索的匹配项)中的关键词被下划线或数字包围,则它不再匹配。连字符、逗号、句号等都可以。在这些情况下,它仍然可以检测到其中的关键词,但是当关键词被下划线或数字包围时,我还需要它来匹配。

2) 在我的关键词包含多个单词(包含 1 个或多个空格)的情况下,我希望在构成我的关键词的每个单词之间允许最大距离/长度。

例如如果我的关键词是:

for sale

... 我匹配的文本是

I have a bike for    sale.

...(关键字词之间的最大距离为 5 个字符),我希望正则表达式匹配:

bike for    sale

但是,如果关键字词之间的距离超过 5 个字符,我不希望它匹配。

此外,这个“距离”不应局限于关键字词之间出现的空格数,因为我还希望匹配以下内容,例如:

I have a bike for _.,1sale.

最后,值得一提的是,在某些情况下,我正在搜索的关键词可能出现不止一次,并且在满足上述条件的情况下,我需要同时匹配两者:

例如

I have a bike for _.,1sale. I've also got a laptop for sale!

因此,我基本上对我目前拥有的内容还有 2 个额外的要求,但我对正则表达式的了解不够深入,无法知道如何实现这些。

【问题讨论】:

  • 第二个问题很容易通过限制量词.{1,5} 解决(除了换行符之外的任何字符出现 1 到 5 次)。但是,如果单词边界阻止匹配关键字,只需删除单词边界,或者使用一种智能方法“知道”在哪里添加它们,在哪里不添加。如果您只想让它在数字和_ 之间匹配,您可能需要检查string.Format( "(?<=\\P{L}|^)({0})(?=\\P{L}|$)", keyphrase )

标签: c# .net regex


【解决方案1】:

我认为您可以使用以下代码来解决 2 个问题:

var regexPattern = string.Format( "(?<!\\p{{L}}){0}(?!\\p{{L}})", keyphrase );
// or
// var regexPattern = string.Format( "(?<=\\P{{L}}|^){0}(?=\\P{{L}}|$)", keyphrase );
regexPattern = regexPattern.Replace( " ", ".{0,5}" );

正则表达式看起来像

(?<!\p{L})key.{0,5}word(?!\p{L})

(?<=\P{L}|^)key.{0,5}word(?=\P{L}|$)

这里是demo 1 / demo 2

请注意,如果您还想以相同的方式匹配内部单词边界,请使用

regexPattern = regexPattern.Replace( " ", "(?=\\P{L}).{0,5}(?<=\\P{L})" );

正则表达式将是

(?<!\p{L})key(?=\P{L}).{0,5}(?<=\P{L})word(?!\p{L})

(?<=\P{L}|^)key(?=\P{L}).{0,5}(?<=\P{L})word(?=\P{L}|$)

demo,它将排除两个单词如果粘在一起不匹配的情况。

【讨论】:

  • 完美,您提供的第一个示例似乎完全符合我的需要。感谢您提供如此完整的答案和演示!
  • 为了完整起见,我发现我需要在 string.Format 行中转义 {L} 的花括号,否则会出错,所以它变成: var regexPattern = string.Format(" (?
  • 我认为在这种情况下字符串连接更好,因为我们避免转义{}。顺便说一句,(?&lt;=\P{L}|^) 等价于(?&lt;!\p{L})(?=\P{L}|$) 等价于(?!\p{L})
  • 最初,我有(?&lt;!\p{L})(?!\p{L}),但我希望模式更明确。
猜你喜欢
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多