正则表达式仅捕获最后一个孩子,而不是全部

时间:2018-08-08 15:33:14

标签: regex

我想在每行上播放一个正则表达式:

127.0.0.1 localhost
# 127.0.0.1 fake
1.2.3.4 foo bar baz

目标是忽略以#开头的时间,否则我想捕获ip及其后的每个字符串。

这是我的尝试:

{^\s?(?<ip>[^#\s]+)(?:\s+(?<domain>[^\s]+))*$}

我的问题是,当我在1.2.3.4 foo bar baz上播放时,它仅捕获baz,而不捕获foobar。我想要每个域。

PS:我正在使用PHP。您可以在这里尝试:https://regex101.com/r/S8Fzlu/1

2 个答案:

答案 0 :(得分:1)

PHP正则表达式引擎或DECLARE @string VARCHAR(100); SET @string = 'Partial:[64][95]'; WHILE PATINDEX('%[^0-9]%', @string) <> 0 SET @string = STUFF(@string, PATINDEX('%[^0-9]%', @string), 1, ''); DECLARE @splitstring NVARCHAR(20) = @string; DECLARE @i INT = 3; WHILE @i < LEN(@splitstring) BEGIN SELECT @splitstring = STUFF(@splitstring, @i, 0, ','); SET @i = @i +3; END; SELECT @splitstring; 不允许在带有量词的组中创建动态捕获组。它仅返回最后捕获的字符串。这就是您看到PCRE被第二捕获组捕获的原因。

但是,您可以利用baz(字边界的种类)并使用\G使用此正则表达式捕获所有字符串:

preg_match_all

RegEx Demo

  • (?:^\h*(?<ip>(?:\d+\.){3}\d+)|(?!^)\G)\h+(?<domain>\S+) 在上一场比赛的末尾或首场比赛的字符串开头断言位置

代码:

\G

输出:

$str = '1.2.3.4 foo bar baz';
$re = '/(?:^\h*(?<ip>(?:\d+\.){3}\d+)|(?!^)\G)\h+(?<domain>\S+)/';
preg_match_all($re, $str, $m);

print_r($m['ip']);
print_r($m['domain']);

答案 1 :(得分:0)

我不确定php RegEx的工作方式,但是可以在JavaScript和C#中使用此RegEx,请尝试一下:

^\s?(?<ip>[^#\s]+)(?:\s+(?<domain>[^.]+)*)$

请注意,我已经将'*'移到了parantese之外。