使正则表达式不捕获OR捕获组

时间:2016-12-27 18:51:26

标签: php regex

所以,我正在努力捕捉字符串包含的那种“语言”片段:

语言代码段位于()内,并且是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如果有第二个语言代码段Fr,它将无法满足正则表达式(1),因为第一个语言代码段{{1正在捕获/占用Enopen parenthesis,导致第二语言代码段comma不匹配...

enter image description here

你们知道如何处理完全捕获所有语言片段吗?我打算用PHP的Fr来获取所有这些。希望有人可以提供帮助。 谢谢!

2 个答案:

答案 0 :(得分:3)

你使用的正则表达式使用逗号围绕语言代码。这意味着,在找到匹配后,索引在逗号后面,并且因为不能匹配,所以正则表达式引擎会跳过该逗号之后的语言。

为了匹配此类重叠匹配,可以使用以下内容:

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

请参阅this regex demo

(?<=[(,])是一个积极的观察,需要在语言代码之前使用,(,而(?=[,)])是一个需要逗号或{{1}的正面预测在语言代码的右边,但是没有使用逗号/括号,它在下一次迭代期间仍然需要匹配。

此处可能的另一种解决方案是使用单词边界(如评论中所述)。单词边界有助于匹配整个单词。

)

请参阅regex demo

答案 1 :(得分:1)

这应该匹配所有:

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

陪同preg_match_all应该做的工作。

说明:

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

就是这样。 :)

Working version

问候。