从开始模式(包括)到下一个开始模式(不包括)的正则表达式

Regex from Begining Pattern (Inclusive) to Next Beginning Pattern (Exclusive)

我想我很擅长 RegEx,但是这个让我难住了。搜索字符串如下所示...

ISA*lots**of~other~data**with~~no terminating **pattern~ISA*lots**of~other~data**with~~no terminating **pattern~ISA*lots**of~other~data**with~~no terminating **pattern~ISA*lots**of~other~data**with~~no terminating **pattern~

我试过的

积极的前瞻,但这并没有捕捉到最后的结果。 (ISA\*(.*(?=ISA\*))?)

一个积极的回顾,但我不知道如何让它变得懒惰。如果不偷懒,就只有一场比赛。但是如果它是惰性的,你会得到正确数量的匹配,但在模式之后只有一个额外的字符。 ISA\*(?<=ISA\*).*?

另一种解决方案是以编程方式 splitexplode 字符串,删除第一个(空)结果,然后将分隔符重新附加到每个结果。事实上,这就是我已经拥有的。但是文件的大小、大量的结果和 post-processing 导致了性能问题。在初步测试中,使用正则表达式似乎提供了一些有价值的性能提升。


正在使用 PHP 处理此问题。该字符串来自 AS400 系统,位于 "EDI Transaction" 文本文件中。我还没有找到任何包含此类文件的工作正则表达式的库。

使用以下基于前瞻的正则表达式:

ISA\*(.*?)(?=ISA\*|$)

regex demo

详情:

  • ISA\* - 文字 ISA* 子串
  • (.*?) - 第 1 组捕获除换行符以外的任何 0+ 个字符(由于惰性 *? 量词),直到(但从匹配中排除).. .
  • (?=ISA\*|$) - ISA* 或字符串结尾(因为它是前瞻性的,与模式匹配的文本不会放入返回的匹配值中)。

同一正则表达式的另一种变体是

ISA\*((?:(?!ISA\*).)*)

regex demo。展开版(效率最高):

ISA\*([^I]*(?:I(?!SA\*)[^I]*)*)

this regex demo

如何使用preg_split

$res = preg_split('/\b(?!^)(?=ISA\*)/', $str);

See php demo at eval.in or regex demo at regex101

如果ISA之前的~是可预测的,使用(?<=~) instead of \b(?!^)

您也可以尝试表达要捕获的内容:

ISA\*(?:[^I]|I[^S]|IS[^A]|ISA[^*])+

使用preg_match_all