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


Regex to only allow alphanumeric, comma, hyphen, underscore and semicolon

我已经有了一些工作代码,但如果可以的话,我需要有人帮助解释为什么它能工作!

如果字符串不是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 # Anything from '0' to '9', meaning 0, 1, 2, ... 9
A-Z # Anything from 'A' to 'Z', meaning A, B, C, ... Z
_-, # Anything from '_' to ',', meaning...uh...hmmm.

_,没有明确的进展,所以正则表达式引擎不确定该如何处理。在字符类中,如果希望从字面上解释连字符,则它必须位于类的开头或末尾(或用反斜杠转义)。因此,其中任何一个都会起作用:

[^,;a-zA-Z0-9_-]
[^-,;a-zA-Z0-9_]
[^a-zA-Z0-9_'-,;]

至于修剪末端,您可以在一个正则表达式替换中完成所有这些:

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

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

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

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