如何确保Bash字符串是字母数字组合,而不包含下划线?

8
我正在为现有脚本添加一个功能,允许用户配置Linux系统的主机名。 我正在执行的规则如下:
  • 必须介于2到63个字符之间
  • 不能以连字符开头或结尾
  • 只能包含字母数字和连字符; 不允许使用其他任何字符(包括下划线,这意味着我不能使用\ W正则表达式符号)
我已解决列表中的前两个问题,但我不知道如何检查一个bash字符串是否只包含字母,数字和连字符。 我认为我可以使用正则表达式来完成此操作,但我无法找出如何做到这一点(我花了过去一小时搜索网络并阅读手册)。
我愿意使用sed,grep或任何其他标准工具,但是不使用Perl或Python。
4个回答

20

好像这就可以了:

^[a-zA-Z0-9][-a-zA-Z0-9]{0,61}[a-zA-Z0-9]$

匹配任何一个字母数字字符,然后匹配最多61个字母数字字符(包括连字符),最后匹配任何一个字母数字字符。字符串长度最小为2,最大为63。它不适用于Unicode。如果您需要它与Unicode一起使用,则需要在a-zA-Z0-9的位置上添加不同的字符类,但原则是相同的。

我认为可以与Unicode一起使用的正确grep表达式是:

^[[:alnum:]][-[:alnum:]]{0,61}[[:alnum:]]$

示例用法:


echo 123-abc-098-xyz | grep -E '^[[:alnum:]][-[:alnum:]]{0,61}[[:alnum:]]$'

result=$(grep -E '^[[:alnum:]][-[:alnum:]]{0,61}[[:alnum:]]$' <<< "this-will-work"); echo $result;

echo "***_this_will_not_match_***" | grep -E '^[[:alnum:]][-[:alnum:]]{0,61}[[:alnum:]]$'

1
你如何使用grep的第二个表达式?我在man页面中寻找开关,但没有成功:我正在回显应该匹配的字符串,但没有输出。 - Alberto Zaccagni
1
@Montecristo:你的测试字符串包含星号和下划线,并以连字符结尾,这些都不符合表达式的要求。 - Welbog
@Welbog:非常感谢,我完全没有意识到如何使用那个:P - Alberto Zaccagni
[:alnum:] 不再包括连字符。 - Alston
@Welbog,我可以问一下为什么这里的 ^ 符号 [^[:alnum:]] 代表否定(所有非字母和数字字符)?但是这里的 ^ 符号 ^[[:alnum:]] 代表“以...开始”?您提到它与“Unicode”很好地配合使用,您有任何参考资料吗?谢谢! - Alston
显示剩余4条评论

3

这是一个bash脚本,用于测试第一个参数是否只包含字母数字或连字符。它将$1的内容“管道”到grep:

#!/bin/bash
if grep '^[-0-9a-zA-Z]*$' <<<$1 ;
  then echo ok;
  else echo ko;
fi

为什么这里的 '^' 代表否定,而不是第一次出现时? - Alston
它的意思是“行首”,因此它和“$”之间的每个字符都必须符合该模式。 - js.

1

这是您需要的最后一个命令:sed -e 's/[^[:alnum:]|-]//g'


1

你可以只使用 Bash 来完成它。

string="-sdfsf"
length=${#string}
if [ $length -lt 2 -o $length -gt 63 ] ;then
    echo "length invalid"
    exit
fi
case $string in
    -* ) echo "not ok : start with hyphen";exit ;;    
    *- ) echo "not ok : end with hyphen";exit ;;   
    *[^a-zA-Z0-9-]* ) echo "not ok : special character";exit;; 
esac

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