匹配逗号分隔列表中两个单词之间的每个项目

Match every item in between two words in a comma separated list

我有一个逗号分隔的数字,如果存在任何关键字,我想匹配 START 之后或 END 之前的每个项目。

我使用

正确地得到了大部分测试用例
(?:.*?START|END.*)(*SKIP)(*F)|\d+

除了 START 出现在 END 之后或存在 STARTEND 的多个实例。

输入 匹配
123,45678,789,777,888,1234 123,45678,789,777,888,1234
123,START,789,777,888,1234 789,777,888,1234
123,45678,789,777,END,1234 123,45678,789,777
123,START,789,777,END,1234 789,777
123,END,789,777,START,1234 123
123,START,789,START,777,END,1234 789,777
123,START,789,END,777,END,1234 789
123,END,789,START,777,END,1234 123

这是我正在尝试的 regex101 project,我正在使用 PCRE2(PHP7.3).

您可以通过添加限制来修复您的模式,以查找前面没有 ENDSTART

(?:^(?:(?!END).)*?START|END.*)(*SKIP)(*F)|\d+
// ^^^^^^^^^^^^^^^

参见regex demo

这里,^(?:(?!END).)*?START(而不是.*?START)匹配

  • ^ - 字符串开头
  • (?:(?!END).)*? - 除换行字符外的任何字符,尽可能少,不启动 END 字符序列
  • START - START 字符序列。

您也可以使用

(?:\G(?!\A)|^(?:(?:(?!END).)*?START)?)(?:(?!END).)*?\K\d+

参见regex demo

详情:

  • (?:\G(?!\A)|^(?:(?:(?!END).)*?START)?) - 上一个成功匹配的结尾 (\G(?!\A)) 或 (|) 字符串的开头 (^) 然后是可选的出现直到第一次出现 START 且前面没有 END ((?:(?:(?!END).)*?START)?)
  • 的任何文本
  • (?:(?!END).)*? - 除换行符以外的任何字符,零次或多次但尽可能少,不会启动 END 字符序列
  • \K - 匹配重置运算符,丢弃到目前为止匹配的所有文本从整体匹配内存缓冲区
  • \d+ - 一位或多位数字。