1

我正在使用以下正则表达式来匹配@username 字符串(twitter 之类的用户名匹配系统)。

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

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

例如:

@8500 <-- 不匹配

@850 <-- 匹配

@8500000000 <-- 匹配

有没有人能想到的简单修改?如果不是,我打算只在 PHP 中进行检查。

谢谢!

4

3 回答 3

3
if(strlen($string) != 4){
    ...regex here...
}
于 2013-03-20T04:32:49.583 回答
3

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

(?<![\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
于 2013-03-20T04:37:19.320 回答
1

您可以使用语法指定正则表达式标记的最小/最大匹配数{min,max},因此您可以使用这样的片段来匹配 1-3 或 5 个或更多数字 ( \d),由非数字字符 ( \D) 包围:

/\D*(\d{1,3}|\d{5,})\D*/
于 2013-03-20T04:36:11.487 回答