否定 bash 正则表达式

否定 bash 正则表达式

当变量hn不是有效的数字整数时,我使用以下模式匹配条件来检测错误。

! [[ "$hn" =~ ^[[:digit:]]+$ ]] && errcode=13

但我得到

bash: /home/flora/int.sh: line 1184: syntax error near unexpected token ! bash: /home/flora/int.sh: line 1184: if ! [[ "$hn" =~ ^[[:digit:]]+$ ]]; then'

答案1

! [[ "$hn" =~ ^[[:digit:]]+$ ]] && errcode=13

在语法上有效bash。它是一个cmd1 && cmd2命令列表,其中cmd1包含! pipeline(运行管道并否定其状态)和cmd2标量变量赋值。pipeline[[ ... ]]用于计算条件表达式的特殊复合命令。其中有 3 个正确分隔的标记。第二个是=~用于扩展正则表达式匹配的运算符。第三个字面意思是所使用的正则表达式。作为正则表达式,它匹配在主题开头和主题结尾之后的区域设置中分类为数字的一个或多个字符。

bash即使在 POSIX 模式下仍然会认为它有效。

在 POSIX sh 中,行为未指定,因为[[是为某些保留的未指定行为。在没有[[特殊关键字的 POSIX sh 实现中,这在语法上仍然有效(除了未加引号的部分$,这可能会让您输入未指定[[领土)​​,但您可能会收到有关未找到命令的错误。

事实上,您得到unexpected token !inif ! [[ "$hn" =~ ^[[:digit:]]+$ ]]; then表明代码是在不需要命令的上下文中找到的。例如,这可能是因为它出现在语句的中间,其中需要case一个模式 or代替(其中将被接受为模式,但下一个标记将是意外的,因为解析器会需要一个or标记)。esacifcase!|)

现在回到否定正则表达式匹配。是的,! [[ "$var" =~ $regexp ]]可以!否定任何命令(实际上,管道)包括那个。您还可以使用!条件表达式运算符:[[ ! "$var" =~ $regexp ]]

但请注意,虽然=~看起来它是受perl's启发=~(本身可能受 awk's 启发~),但不支持perl's (或awk's)运算符。!~

至于那个特定的正则表达式在其他问答中有更详细的解释,如果您只想接受阿拉伯十进制数字,则通常应该避免输入验证类似[0-9]或之类的内容。[[:digit:]]0123456789

所以:

[[ ! "$hn" =~ ^[0123456789]+$ ]]

或者(使用 glob 模式而不是正则表达式):

[[ "$hn" != +([0123456789]) ]]

shopt -s extglob(旧版本中需要bash+(...)ksh 扩展 glob 才能被识别)

会更好。

在标准sh语法中:

case "$hn" in
  ('' | *[!0123456789]*) true;;
  (*) false;;
esac

您可能还想拒绝带有前导 0 的数字(0 本身除外),这些数字在某些情况下被解释为八进制(导致某些数字出现错误,例如019)或大于将要使用它们的内容所支持的数字。

相关内容