PHP - 用正则表达式匹配一串特殊字符的字符串

11

早上好SO。我正在尝试确定一个字符串是否包含一组特定的字符。

我知道应该使用preg_match来实现这个,但我对正则表达式的知识很少,也无法从本站的其他帖子中获得任何信息。因为大多数人只想将字符串限制为a-z、A-Z和0-9。但我确实希望允许一些特殊字符,例如:!@£和其他不在下面的字符串中的字符。

要匹配的字符:# $ % ^ & * ( ) + = - [ ] \ ' ; , . / { } | \ " : < > ? ~

private function containsIllegalChars($string)
{
    return preg_match([REGEX_STRING_HERE], $string);
}

我最初是用JavaScript编写匹配算法的,它只是通过循环遍历字符串中的每个字符,然后再循环遍历另一个字符串中的每个字符,直到找到匹配项。回顾过去,我简直不敢相信自己竟尝试使用这种过时的方法。随着json的出现(和应用程序的重写!),我正在将匹配操作切换到php,并通过json返回错误消息。

我希望有正则表达式专家能帮助将上述字符串转换为一个正则表达式字符串,但任何反馈都将不胜感激!


2
呃... Unicode 目录包含超过 100,000 个字符。 您确定只想过滤出您列出的几个吗? 您不喜欢白名单方法吗? - Álvaro González
幸运的是,在这种情况下 - 黑名单是足够的。 - Stann0rz
4个回答

14

针对“不允许字符列表”的正则表达式并非强制要求。

您可以查看strpbrk。它应该可以完成您需要的工作。

以下是使用示例:

$tests = array(
    "Hello I should be allowed",
    "Aw! I'm not allowed",
    "Geez [another] one",
    "=)",
    "<WH4T4NXSS474K>"
);
$illegal = "#$%^&*()+=-[]';,./{}|:<>?~";

foreach ($tests as $test) {
    echo $test;
    echo ' => ';
    echo (false === strpbrk($test, $illegal)) ? 'Allowed' : "Disallowed";
    echo PHP_EOL;
}

http://codepad.org/yaJJsOpT


这样做还算可以 - 它比preg_match更有效吗? - Stann0rz
尽管这不是我要求的,但这是一个更好的解决方案,因此我接受了你的答案,谢谢! - Stann0rz
注意到这个旧评论,给出的测试用例并没有针对preg_match进行优化。这里有一个更好的。这并不改变strpbrk的效率,但会为preg_match提供一个真实的值。 - Touki

12
return preg_match('/[#$%^&*()+=\-\[\]\';,.\/{}|":<>?~\\\\]/', $string);

完美解决了我提出的问题,谢谢Arnold。不过看了一下strpbrk,它可能比我最初想使用的preg_match更好。 - Stann0rz

4
我认为您要做的事情可以通过包含想要允许的字符来大大简化,像这样:
preg_match('/[^\w!@£]/', $string)

这里是一个快速的解释:
  • [^] 表示不包含
  • \w 表示字母和数字
  • ! @ £ = 列出你想要允许的字符

3
$pattern = preg_quote('#$%^&*()+=-[]\';,./{}|\":<>?~', '#');

var_dump(preg_match("#[{$pattern}]#", 'hello world')); // false
var_dump(preg_match("#[{$pattern}]#", 'he||o wor|d')); // true
var_dump(preg_match("#[{$pattern}]#", '$uper duper')); // true

很可能,你可以缓存$pattern,具体取决于你的实现方式。
(尽管超出正则表达式范畴,如此提到的strpbrk是最好的选择)

你说得对,strpbrk 对我需要的东西来说更好。但我之前没有看到过 preg_quote,它似乎是一个非常方便的小函数,所以感谢你指出它! - Stann0rz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接