Shell 模式匹配和算术运算符 (+ - * / %)

Shell 模式匹配和算术运算符 (+ - * / %)

这看起来很简单,但事实并非如此:

[[ "1234+5678" =~ [0-9]+(\s*(\-|\*)\s*[0-9]+)* ]] && echo $?

返回一个0.然而,实际上不应该这样做,因为只允许减号 ( -) 和乘法 ( *) 运算符。另外,我在网上找到了一些正则表达式工具并尝试匹配此模式:结果是空字符串。 (如预期)

在散文中,这扩展正则表达式如下:

  • 查找号码(必填)
  • 检查是否有一些空白
  • 运算符必须是 a-或 a*
  • 检查是否有一些空白(再次)
  • 查找另一个数字(如果前面有运算符,则必须存在)

此外,括号中的表达式后面的星号表示第二到第 n 个运算符数字对是可选的。

我这里的想法错误在哪里?

答案1

如果没有标记,正则表达式(右侧部分)可以匹配任何部分的字符串。所以你的变体匹配1234。为了满足要求,您必须使用标记:

[[ "1234+5678" =~ ^[0-9]+(\s*(\-|\*)\s*[0-9]+)*$ ]] ; echo $?

更短(如果你愿意的话):

[[ "1234+5678" =~ ^[0-9\ *-]+*$ ]] ; echo $?

答案2

您的表达式返回 0,因为它与第一个数字匹配。锚定正则表达式以使其执行您想要的操作:

[[ "1234+5678" =~ ^[0-9]+( *(-|\*) *[0-9]+)*$ ]] && echo $?

附注:(1) 您不需要引用-,并且 (2)\s不被识别为 ERE。

答案3

[[ "1234+5678" =~ [0-9]+(\s*(\-|\*)\s*[0-9]+) ]] ; echo $?

*正则表达式末尾的正则表达式运算符允许 () 内的表达式任意次数重复,也不允许重复。所以你从一开始就匹配[0-9]+,其余的都是可选的。

如果删除*或将其替换为 a,则+表达式将按预期返回。

此外,括号中的表达式后面的星号表示第二到第 n 个运算符数字对是可选的。

这就是错误:这*意味着any 运算符是选项。使用+运算符!

好吧,这不是答案,但您可以使用表达式并查看结果是否为空:

echo "1234*5678"|sed 's/[0-9]\+\([ \*\-][0-9]\+\)*//'

相关内容