【问题标题】:make regex not capture the OR capture group使正则表达式不捕获 OR 捕获组
【发布时间】:2016-12-27 18:51:26
【问题描述】:

所以,我正在努力捕捉字符串包含什么样的“语言”sn-p:

语言 sn-p 在 () 内部,是以下组合:En,Fr,De,Es,It

例子:

File (En,Fr,De,Es,It).doc    <== should match all 5 languages
File (En,Fr) (Required).doc  <== should match `En` and `Fr`
File (Enfoo,Fr).doc          <== should match only `Fr`
File (E,Fr).doc              <== should match only `Fr`

我当前的正则表达式:

((\(|,)En(\)|,))|((\(|,)Fr(\)|,))|((\(|,)De(\)|,))|((\(|,)Es(\)|,))|((\(|,)It(\)|,))

什么意思:

((\(|,)  <== either starts with `open parenthesis` or `comma`  (1)
En       <== the language                                      (2)
(\)|,))  <== either ends with `close parenthesis` or `comma`   (3)

然后我只需附加正则表达式OR (|)

您可以看到的问题:regexr.com/3ev6p 是,如果有第二种语言 sn-p 即 Fr 它不会满足正则表达式 (1) 因为第一种语言 sn-p En 正在捕获/已经占用open parenthesiscomma,导致第二语言sn-p Fr 不匹配...

你们知道如何处理完全捕获所有的语言 sn-p 吗?我打算使用 PHP 的preg_match_all() 来获得所有这些。希望有人可以提供帮助。 谢谢!

【问题讨论】:

  • 不确定我是否理解正确,但这是您想要的吗? regex101.com/r/PAwqGg/1
  • 这个regexr.com/3ev6s 怎么样?
  • @Mi-Creativity,边界应该围绕所有语言。 ;)
  • @sinisake @Mi-Creativity 谢谢\b 他们在学校教这个时我缺席了。谢谢!
  • @sinisake 这是真的,如果他在所有语言中都有这个问题(像 Enfoo 这样的词),谢谢你提到它:)

标签: php regex


【解决方案1】:

您拥有的正则表达式使用语言代码周围的逗号。这意味着,在找到匹配项后,索引位于逗号之后,并且由于无法匹配,正则表达式引擎会跳过该逗号之后的语言。

为了匹配这样的重叠匹配,可以使用lookarounds:

(?<=[(,])(En|Fr|De|Es|It)(?=[,)])
^^^^^^^^^                ^^^^^^^^

this regex demo

(?&lt;=[(,]) 是一个正向lookbehind,在语言代码前需要,((?=[,)]) 是一个正向lookahead,需要在语言代码右侧使用逗号或),但是逗号/括号没有被消耗,它仍然需要在下一次迭代中匹配。

这里可能的另一个解决方案是使用单词边界(正如在 cmets 中已经描述的那样)。单词边界有助于匹配整个个单词。

\b(En|Fr|De|Es|It)\b

regex demo

【讨论】:

  • 哇,我也不知道positive lookbehind 也不知道positive lookahead。我不应该逃学。标记为附加解释的答案。
【解决方案2】:

这应该匹配所有:

 (?<=,|\()(\w\w)(?=,|\))

伴随preg_match_all应该做的工作。

解释:

  • 后视断言(应以“,”或“(”)开头
  • 两个单词字符(因此您不必事先指定要定位的语言)。
  • 前瞻断言(应后跟“,”或“)”)

就是这样。

Working version.

【讨论】:

    猜你喜欢
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 2018-03-11
    • 1970-01-01
    相关资源
    最近更新 更多