我需要一种机制来查找字符串中的数字,该数字由非数字字符或字符串的开头/结尾或特殊分隔符(在本例中为43)包围。以下是一些例子:
所有这些都应该导致匹配12345678
。目前我正在使用以下正则表达式:
(?<=^|\D|43)([0-9]{8})(?=$|\D|43)
这个表达式效果很好,但有一个缺陷。如果数字以43开头但不以43结尾,我也得到肯定的结果。以下是我得到那些“错误”结果的例子:
我现在需要的是正则表达式的构造,以便知道匹配的字符串是否以43开头,然后仅在结束时以43结尾才返回它。
答案 0 :(得分:3)
您可以在lookbehind中使用正向前瞻检查:
(?<=^|\D|43(?=[0-9]{8}43))[0-9]{8}(?=43|\D|$)
^^^^^^^^^^^^^^
请参阅regex demo。
现在,仅当43
在之前且在8个随机数字之后才会发生匹配。
<强>详情:
(?<=^|\D|43(?=[0-9]{8}43))
- 匹配字符串中的位置
之前是
^
- 字符串开头\D
- 非数字符号43(?=[0-9]{8}43)
- 43
子字符串,后跟任意8位数字,然后是43
substring [0-9]{8}
- 正好是8位数(?=43|\D|$)
- 必须遵循8位数字:
43
- 43
数字序列\D
- (= [^0-9]
)任何非数字符号$
- 字符串结束。这是我自己的基于conditional的正则表达式,用于同一任务(可以在.NET,PCRE中使用,但不能在Java中使用):
(?<=^|[^0-9]|(43))[0-9]{8}(?=(?(1)43|(?:[^0-9]|$)))
这是一个RegexStorm demo,在测试.NET regexp时非常有用。
Conditional construct上的一些背景信息:
此语言元素尝试匹配两种模式中的一种,具体取决于它是否可以匹配初始模式。它的语法是:
(?( expression ) yes | no )
其中expression是要匹配的初始模式,yes是匹配表达式时要匹配的模式,如果表达式不匹配,则no是匹配的可选模式。正则表达式引擎将表达式视为零宽度断言;也就是说,正则表达式引擎在评估表达式后不会在输入流中前进。
因此,lookbehind中的(43)
将捕获转移到第1组,然后在条件(?(1)43|(?:[^0-9]|$))
,(?(1))
内检查第1组是否匹配完全如果是,43
匹配,否则尝试(?:[^0-9]|$)
(任何非数字或字符串结尾。
答案 1 :(得分:2)
您可以使用conditional:
(?<=^|\D|(43))[0-9]{8}(?(1)(?=43)|(?=$|\D))
在第1组中捕获第一个43
,稍后在条件查询中捕获第1组是否与任何内容匹配。
如果你的正则表达式引擎不支持条件,你可以尝试这个“自己创建条件”解决方法:
(?<=^|\D|()43)[0-9]{8}(?=(?:\1(?:43)|(?!\1)(?:\D|$)))
我们的想法是用这样的替换替换条件(text)(?(1)a|b)
:()text(?:\1a|(?!\1)b)