正则表达式 (PCRE):匹配所有以字符串存在为条件的数字
Regex (PCRE): Match all digits conditional upon presence of a string
使用 PCRE,我只想捕获一行中的所有数字,但前提是特定字符串(例如“STRING99”)出现在该行的任何位置。
例如,考虑这两种情况:
a1 STRING99 2b c3d
a1 2b c3d
在第一种情况下,我希望结果为“19923”。
在第二种情况下,我想要一个空结果。
我不确定这是否可能。它可能适用于可变长度的后视,但这在 PCRE 中不受支持。此外,像 (?=.*STRING99.*$)(\D|(\d))*
这样的东西会起作用,但是“重复的捕获组只会捕获最后一次迭代”,这意味着第二个捕获组只捕获最后一个数字。我无法为此找到解决方法。
(这显然不难实现连续2次正则表达式运算,但我希望它在一个公式中。)
我们可以使用带有回调函数的正则表达式替换:
$output = preg_replace_callback('/^.*\bSTRING99\b.*$/', function ($match) {
return preg_replace("/\D+/", "", $match[0]);
}, 'a1 STRING99 2b c3d');
echo $output; // prints 1992
这里的做法是首先只匹配包含STRING 99
的输入。然后在这样的匹配上,我们去掉所有非数字字符。不匹配将不会完成此替换。
您可以使用
(?:\G(?!^)|^(?=.*STRING99)|^.*(*ACCEPT))\d*\K\D+
请参阅 regex demo(我将 \D
替换为 [^\d\n]
仅出于演示目的,因为测试是针对多行字符串执行的)。
详情
(?:\G(?!^)|^(?=.*STRING99)|^.*(*ACCEPT))
- 如果在任何 0+ 个字符之后有 STRING99
字符串(参见 ^(?=.*STRING99)
)或(否则)整个字符串与 ^.*
匹配并返回成功匹配(不进一步解析模式)
\d*
- 消耗了 0 个或更多数字
\K
- 并从匹配内存缓冲区中丢弃
\D+
- 1 个或多个 non-digit 个字符(最终将被删除)。
您可以在 preg_replace
:
中使用此 PCRE 正则表达式
^(?!.*STRING99).*(*SKIP)|\D+
正则表达式详细信息:
^
: 开始
(?!.*STRING99)
:Lokahead 检查输入 中是否有STRING99
.*(*SKIP)
: 匹配输入的剩余部分直到结束并跳过它
|
: 或
\D+
: 匹配 1+ non-digit
PHP代码:
$repl = preg_replace('~^(?!.*STRING99).*(*SKIP)|\D+~', '', $str);
使用 PCRE,我只想捕获一行中的所有数字,但前提是特定字符串(例如“STRING99”)出现在该行的任何位置。
例如,考虑这两种情况:
a1 STRING99 2b c3d
a1 2b c3d
在第一种情况下,我希望结果为“19923”。 在第二种情况下,我想要一个空结果。
我不确定这是否可能。它可能适用于可变长度的后视,但这在 PCRE 中不受支持。此外,像 (?=.*STRING99.*$)(\D|(\d))*
这样的东西会起作用,但是“重复的捕获组只会捕获最后一次迭代”,这意味着第二个捕获组只捕获最后一个数字。我无法为此找到解决方法。
(这显然不难实现连续2次正则表达式运算,但我希望它在一个公式中。)
我们可以使用带有回调函数的正则表达式替换:
$output = preg_replace_callback('/^.*\bSTRING99\b.*$/', function ($match) {
return preg_replace("/\D+/", "", $match[0]);
}, 'a1 STRING99 2b c3d');
echo $output; // prints 1992
这里的做法是首先只匹配包含STRING 99
的输入。然后在这样的匹配上,我们去掉所有非数字字符。不匹配将不会完成此替换。
您可以使用
(?:\G(?!^)|^(?=.*STRING99)|^.*(*ACCEPT))\d*\K\D+
请参阅 regex demo(我将 \D
替换为 [^\d\n]
仅出于演示目的,因为测试是针对多行字符串执行的)。
详情
(?:\G(?!^)|^(?=.*STRING99)|^.*(*ACCEPT))
- 如果在任何 0+ 个字符之后有STRING99
字符串(参见^(?=.*STRING99)
)或(否则)整个字符串与^.*
匹配并返回成功匹配(不进一步解析模式)\d*
- 消耗了 0 个或更多数字\K
- 并从匹配内存缓冲区中丢弃\D+
- 1 个或多个 non-digit 个字符(最终将被删除)。
您可以在 preg_replace
:
^(?!.*STRING99).*(*SKIP)|\D+
正则表达式详细信息:
^
: 开始(?!.*STRING99)
:Lokahead 检查输入 中是否有.*(*SKIP)
: 匹配输入的剩余部分直到结束并跳过它|
: 或\D+
: 匹配 1+ non-digit
STRING99
PHP代码:
$repl = preg_replace('~^(?!.*STRING99).*(*SKIP)|\D+~', '', $str);