匹配所有出现的A组,然后匹配两个B组,并使用填充字符

时间:2019-03-15 13:32:39

标签: php regex

我有一个带有以下“有效”模式的字符串,该字符串会重复多次: 一组特定的字符,例如“ ab”,任意数量的其他字符,例如“ xx”,另一组特定的字符,例如“ cd”,任意数量的其他字符,例如“ xx”。

因此,有效序列为: “ abxcdabxxcdabxcdxx”

我正在尝试检测以下特定格式的无效序列:“ abxxcdxxcd”,并删除中间的“ cd”以使其有效:“ abxxxxcd”

我尝试了以下正则表达式:

/(?<=ab).*(cd).*(?=ab)/gsU

它适用于单个序列,但不适用于以下字符串: “ abxx cd xcdxxabxcdxxabx cd xxcd”,其中包含无效序列,后跟有效序列,然后是另一个无效序列。我想用粗体捕获两个组。

请注意,其他字符“ xx”可能包含任何内容,包括换行符。但是,除非我指定了无效的情况,否则它们绝不会包含字符串“ ab”或“ cd”。

以下是相应的regex101链接:https://regex101.com/r/U9pRfo/1

编辑:

Wiktor's answer为我效劳。但是,当在非常大的字符串上使用该正则表达式时,我在php中得到了PREG_JIT_STACKLIMIT_ERROR。我最后只是将字符串分成较小的块,然后重建字符串,效果很好。

1 个答案:

答案 0 :(得分:1)

您可以使用

'~(?:\G(?!^)|ab)(?:(?!ab).)*?\Kcd(?=(?:(?!ab).)*?cd)~s'

请参见regex demo

  • (?:\G(?!^)|ab)-匹配ab或上一个匹配项结尾的捕捉组
  • (?:(?!ab).)*?-匹配任何不开始ab字符序列的char,最多0次或更多次
  • \K-匹配重置运算符
  • cd-子字符串
  • (?=(?:(?!ab).)*?cd)-一个正向先行,它需要任何char,0个或多个重复(尽可能少的重复),并且不会开始ab char序列,然后再开始cd char序列。 / li>