我这样做是为了验证用户名:
if [[ "$username" =~ ^[a-z][_a-z0-9]{2,17}$ ]]; then
但实际上,接受包含 é、ç、à 等 unicode 字符的用户名。我应该使用什么正则表达式类将字符串限制为仅 ascii 字母 (a, b, c, d ... z) ?
您应该可以通过第一次设置来做到这一点LC_ALL=C
(可能是暂时的,以免影响其他任何东西)。更现代的正则表达式引擎允许语言环境可以将重音字符折叠到它们的基本字符上(或者至少对它们进行排序,使它们介于a
和之间z
)。
由于 C 语言环境只知道 ASCII,这应该可以解决问题。
例如,请参阅以下脚本:
#!/bin/bash
username=amélie_314159
for locale in '' 'C' ; do
export LC_ALL="${locale}"
printf "LC_ALL set to %-3s: '%s' is " "'$LC_ALL'" "${username}"
if [[ "${username}" =~ ^[a-z][_a-z0-9]{2,17}$ ]] ; then
echo valid
else
echo invalid
fi
done
输出:
LC_ALL set to '' : 'amélie_314159' is valid
LC_ALL set to 'C': 'amélie_314159' is invalid
防弹的方法是简单地拼写[a-z]
为[abcdefghijklmnopqrstuvwxyz]
. 那里!自 1970 年 1 月 1 日 00:00:00 以来,任何 shell 都不受语言环境或有趣的字符类的影响。面向未来,无论您的操作系统供应商、shell 供应商、Unix 标准化流程或 BOFH 认为什么很酷。
有一个额外的变量lc
,比如
lc=abcdefghijklmnopqrstuvwxyz
正则表达式甚至变得可读:
[$lc][_0-9$lc]{2,17}
这就是高度健壮和可移植的configure
脚本所做的。
使用以下内容:
if [[ "$username" =~ ^[\x00-\x7f]{2,17}$ ]]; then
在使用正则表达式检查用户名是否具有正确的长度等之前,您应该清理输入字符串。这意味着您应该将实际允许的内容列入白名单,而不是将不允许的内容列入黑名单。在这种情况下,我们将在实际的正则表达式之前使用 egtr
来预先删除所有不需要的字符。当进行正则表达式检查时,它变得更加简单。
echo "abc[日本語][ひらがな][カタカナ][äüéçà]abc" | tr -dc "a-zA-Z"
这只会留下abcabc
余数。