双正则表达式匹配

Double regex matches

我 preg_match_all 使用不同的模式遍历字符串。有时这些模式看起来很像,但略有不同。

现在我正在寻找一种方法来阻止模式 A 匹配只有模式 B - 在 4 位数字前面有一个 'T' - 应该匹配的字符串。


我 运行 遇到的问题是模式 A 也匹配模式 B:

甲:

(\d{4})(A|B)?(C|D)?

...匹配 1234、1234A、1234AD 等

乙:

我还有一个模式:

T(\d{4})\/(\d{4})

... 匹配如下字符串:T7878/6767

结果

当 运行 a preg_match_all on "T7878/6767 1234AD",A 将给出以下匹配:

7878, 6767, 1234AD

有没有人建议如何防止 A 在字符串中匹配 B,例如 "Some text T7878/6767 1234AD and some more text"?

非常感谢您的帮助!

根据您的要求,您当前的正则表达式并没有真正起作用。 (A|B)?(C|D)? 永远不会匹配 AB。所以我认为你的意思是 [ABCD]

这是您的新正则表达式:

T(\d{4})\/(\d{4}) (\d{4}[ABCD]*)

对于字符串输入:

T7878/6767 1234AB

我们得到组:

Match 1
Full match  0-17    `T7878/6767 1234AB`
Group 1.    1-5 `7878`
Group 2.    6-10    `6767`
Group 3.    11-17   `1234AB`

Regex101

有边界的场景

如果您只想匹配某些边界内的那些特定字符串,请在模式的每一侧使用这些边界模式。

如果您希望在每次匹配之前有一个空白边界,则在模式的开头添加 (?<!\S) 负向回顾。如果您希望在匹配结束时出现空白边界,请添加 (?!\S) 负先行。如果可以有任何字符(就像你原来的问题一样),那么 SKIP-FAIL 是唯一的方法(见下文)。

因此,在第一种情况下,您可以使用

(?<!\S)(\d{4})([AB]?)([CD]?)(?!\S)

(?<!\S)T(\d{4})\/(\d{4})(?!\S)

参见 Pattern 1 demo and Pattern 2 demo

没有特定边界的场景

您需要确保在使用第一个模式解析字符串时跳过第二个模式。为此使用 SKIP-FAIL technique

'~T\d{4}/\d{4}(*SKIP)(*F)|(\d{4})(A|B)?(C|D)?~'

参见regex demo

如果不需要捕获组,可以简化为

'~T\d{4}/\d{4}(*SKIP)(*F)|\d{4}[AB]?[CD]?~'

another demo

详情

  • T\d{4}/\d{4} - T 后跟 4 位数字,/ 和另外 4 位数字
  • (*SKIP)(*F) - 匹配的文本被丢弃,从匹配的文本末尾开始搜索下一个匹配项
  • | - 或
  • \d{4}[AB]?[CD]? - 4 位数字,然后可选 AB,然后可选 CD.

您的语法非常具体,因此您只需要使用正则表达式即可。摆脱你所有的捕获组,因为他们把事情搞砸了。您只需要两个与您的字符串语法完全匹配的组。

第一组查找单词边界,然后是 T,然后是 4 位数字,然后是/然后是 4 位数字和一个分词符。

第二组匹配 4 位数字,然后匹配字母 A-D 0 到 2 次。它有一个负向后视,所以只有在 4 位数字之前有一个空白字符时才会匹配

(\bT\d{4}\/\d{4}\b)|(?<!\S)(\d{4}[A-D]{0,2})

预匹配所有输出:

Array
(
[0] => Array
(
[0] => T7878/6767
[1] => 1234AB
)

[1] => Array
(
[0] => T7878/6767
[1] => 
)

[2] => Array
(
[0] => 
[1] => 1234AB
)

)