为什么[a-zA-Z]匹配数字和字母?

时间:2013-06-17 04:24:54

标签: php regex

我想要一个允许letters and only而不是digits的变量。

该变量可以位于字符串中的任何位置。

看看这个,

$pattern = '~user/(:var)~';

$pattern = str_replace('(:var)', '([a-zA-Z])', $pattern);

// Note, the variable contain both numbers and letters
$test = 'user/dave123';

$r = preg_match($pattern, $test); 

var_dump($r); //1 Success (I don't want this)

我想要的只是,

如果变量仅包含字母,则preg_match()应返回1, 但如果那个包含至少一个数字,则preg_match()应立即返回0,

应该定义哪个regex而不是([a-zA-Z])以及为什么([a-zA-Z])匹配数字和字母!?

4 个答案:

答案 0 :(得分:6)

正则表达式匹配测试值的这个子字符串:user/d

如果要检查整个字符串,请在模式中添加start(^)和end($)个锚点:

$pattern = '~^user/(:var)$~';

要检查字符串的开头/结尾 OR 另一个分隔符,例如/,它将如下所示:

$pattern = '~(?:^|/)user/(:var)(?:$|/)~';

这将迫使它考虑整个值,直到字符串的结尾或下一个/ ...阻止您在问题中遇到的部分匹配。

?:表示non-capturing group,这意味着额外的()群组不会在您的匹配结果列表中结束)

您还需要允许[a-zA-Z]类重复+,否则它只会匹配单字符用户名:

$pattern = str_replace('(:var)', '([a-zA-Z]+)', $pattern);

答案 1 :(得分:3)

您需要分别使用^$开始结束。

'~^user/(:var)$~'

匹配是因为,您的字符串中包含userdave

答案 2 :(得分:1)

您的模式意味着“a-z或A-Z之间的任何字符之一”,这就是它匹配的原因。它不提供检查以确定它是否匹配,并且它不会匹配重复的字符。

而不是那种方法,为什么不尝试更简单的方法。因为您只想知道字符串是否包含数字:

$haystack = 'user/dave123';
foreach(range(0,9) as $i) {
    if (strpos($haystack,$i) === FALSE)) {
         return 1;
    }
}
return 0;

这将停在找到的第一个号码上。

答案 3 :(得分:0)

模式可能与字符串中的第一个字符匹配,而不是与整个字符串匹配。要匹配整个字符串,请尝试

"/^[a-z]+$/i"

这应该给你一个不区分大小写的字母只匹配整个字符串(^$字符串的开头字符串的结尾分隔符)。

还有一些方便的内置PHP函数,如ctype_alpha(),它们完全相同。