我写了一个正则表达式,我在rubular.com中测试过,它返回了4个匹配项。测试主题可以在http://pastebin.com/49ERrzJN找到,PHP代码如下。由于某种原因,PHP代码仅返回前2个匹配项。如何使它匹配所有4?它似乎与贪婪有关。
$file = file_get_contents('x.txt');
preg_match_all('~[0-9]+\s+(((?!\d{7,}).){2,20})\s{2,30}(((?!\d{7,}).){2,30})\s+([0-9]+)-([0-9]+)-([0-9]+)\s+(F|M)\s+(.{3,25})\s+(((?!\d{7,}).){2,50})~', $file, $m, PREG_SET_ORDER);
foreach($m as $v) echo 'S: '. $v[1]. '; N: '. $v[3]. '; D:'. $v[7]. '<br>';
答案 0 :(得分:2)
你的正则表达式非常懒散。在regex101.com上试用之后,我发现它会在PHP上超时(但不是JS,无论出于何种原因)。我很确定超时发生在大约50,000步。实际上,现在为什么你没有使用在线PHP正则表达式测试器是有道理的。
我不确定这是否是您问题的根源,但there is a default memory limit in PHP:
memory_limit [默认:]“128M”
[history:] PHP 8.0之前的“8M”,PHP 5.2.0中的“16M”
如果您使用m
ultiline修饰符(我假设preg_match_all
实际上添加了g
lobal修饰符),您可以使用此正则表达式只需1282步即可找到所有4个匹配项:
^ [0-9]+\s+(((?!\d{7,}).){2,20})\s{2,30}(((?!\d{7,}).){2,30})\s+([0-9]+)-([0-9]+)-([0-9]+)\s+(F|M)\s+(.{3,25})\s+(((?!\d{7,}).){2,50})
实际上,我添加了只有2个字符。他们在开头,锚^
和文字空间。
答案 1 :(得分:1)
如果你必须写一个长模式,首先要做的是让它可读。为此,请使用允许注释和自由间距的详细模式(x修饰符),并使用命名捕获。
然后你需要准确描述你在寻找什么:
^
和$
与修饰符m一起使用,并使用\h
类(仅包含水平空格)而不是{{1 }。class。\s
来描述您的字段不得包含的内容,描述该字段可以包含的内容。(?:(?!.....).){m,n}
而不是非捕获组,以避免无用的回溯。图案:
(?>...)
如果您想知道模式出了什么问题,可以使用函数preg_last_error()