是否有可能修改此正则表达式为不匹配字符串,如果它的4位数字


Is it possible to modify this regex to NOT match string if its 4 digits?

我使用以下regex来匹配@username字符串(twitter类似于用户名匹配系统)。

(?<!['w@])@(['w@]+(?:[.!]['w@]+)*)

这段代码对我来说是完美的,但是想要排除一种特定的情况:如果匹配的字符串是一组4位数字。只有4位数。如果有3位或5位数字,则应该像现在一样继续匹配。

例如:

@8500 <—don't match

@850 <——match

@8500000000 <——match

有没有任何人都能想到的简单修改?如果没有,我打算在PHP中做检查。

谢谢!

使用负向前看(?!...),您可以检查以下模式在当前位置是否匹配:

(?<!['w@])@(?!'d'd'd'd'b)(['w@]+(?:[.!]['w@]+)*)

这里讨论的负前瞻性是(?!'d'd'd'd'b)。该模式将匹配四个数字,然后是单词边界。通过反向向前看,这将匹配任何,而不是四位数字,然后是单词的结尾。

这假设一个有效的用户名不包含任何会导致词边界匹配的字符。如果@1234-hello是一个有效的用户名,这将失败,您需要在PHP中执行匹配。

下面是一些测试用例:

<?php
function test($test) {
    $pattern = '/(?<!['w@])@(?!'d'd'd'd'b)(['w@]+(?:[.!]['w@]+)*)/';
    echo (preg_match($pattern, $test) ? 'Matches' : 'No match') . "'n";
}
test('Hello @test world'); // Matches
test('Hello @123 world'); // Matches
test('Hello @1234 world'); // No match
test('Hello @12345 world'); // Matches
test('Hello @test1234 world'); // Matches
test('Hello @1234test world'); // Matches
test('Hello @1234-test world'); // No match
test('Hello @1234_test world'); // Matches
if(strlen($string) != 4){
    ...regex here...
}

您可以使用{min,max}语法指定regex令牌的最小/最大匹配数,因此您可以使用这样的代码片段来匹配1-3或5个或更多数字('d),由非数字字符('D)包围:

/'D*('d{1,3}|'d{5,})'D*/