Php Regex只允许字母数字、逗号、连字符、下划线和分号

Php Regex只允许字母数字、逗号、连字符、下划线和分号,php,regex,preg-replace,Php,Regex,Preg Replace,我已经有一点工作代码,但我需要有人帮助解释为什么它可以工作,如果他们可以 如果字符串不是a-z、a-z、0-9、逗号、分号、下划线或连字符(最终应表示单个用户名或逗号/分号分隔的用户名列表),我将使用PHP替换字符串中的任何内容 以下工作: $data = preg_replace('/[^,;a-zA-Z0-9_-]/s', '', $data); 但以下情况并非如此: $data = preg_replace('/[^a-zA-Z0-9_-,;]/s', '', $data); 为什么只

我已经有一点工作代码,但我需要有人帮助解释为什么它可以工作,如果他们可以

如果字符串不是a-z、a-z、0-9、逗号、分号、下划线或连字符(最终应表示单个用户名或逗号/分号分隔的用户名列表),我将使用PHP替换字符串中的任何内容

以下工作:

$data = preg_replace('/[^,;a-zA-Z0-9_-]/s', '', $data);
但以下情况并非如此:

$data = preg_replace('/[^a-zA-Z0-9_-,;]/s', '', $data);
为什么只有逗号和分号在开头时才起作用?将它们放在末尾似乎会破坏一切(这是我最初遇到的/[^a-zA-Z0-9_-]/s时尝试的方法

顺便说一句,我还使用以下方法修剪任何尾随的分号(复数)或逗号(复数),有人可能会建议一种更有效和/或更优雅的方法来完成此操作:

if(preg_match('/;$/', $data))
{
    $data = rtrim($data, ';' );
}
if(preg_match('/,$/', $data))
{
    $data = rtrim($data, ',' );
}

感谢您的帮助:)

我认为重要的是连字符的位置——必须在开始或结束处使用连字符(文字),否则它将用于定义范围

您可以对连字符进行转义,并将其放在正则表达式中的任何位置,如下所示
\-


至于后面的分号和逗号,试试这个
/[,;]+$/
,它应该匹配结尾处的任何逗号和分号,即使它们很多。

不是逗号和分号造成问题;是连字符。看看你的角色类的部分并考虑他们的意思:

0-9#从“0”到“9”的任意值,表示0、1、2、。。。9
A-Z#从“A”到“Z”的任何词,意思是A、B、C、。。。Z
_-从"到",意思是"嗯"嗯。
\uu
,没有明确的进展,因此正则表达式引擎不确定如何处理这个问题。在字符类中,如果希望按字面解释连字符,则它需要位于类的最开头或结尾(或用反斜杠转义)。因此,其中任何一项都将起作用:

[^,;a-zA-Z0-9_-]
[^-,;a-zA-Z0-9_]
[^a-zA-Z0-9_\-,;]
至于修剪末端,您可以在一个正则表达式替换中完成所有这一切:

$data = preg_replace('/[^,;a-zA-Z0-9_-]|[,;]$/s', '', $data);

+1还要注意的是,在第二个模式中,您可以简单地使用反斜杠来转义流氓连字符,它的工作原理与第一个模式相同:
'/[^a-zA-Z0-9_ \-,;]/s'
“从
\uu
”没有明确的顺序:有一个非常明确的顺序:它基于Unicode表。然而,在这种情况下,Unicode表中,
\uu
位于
之后,因此不可能有一个范围。@Xufox-好吧,这将使它成为一个回归,不是吗?;)关键是正则表达式引擎不理解任何进程。但是你是对的,从
。我直到现在才知道,谢谢你!