我有一个Bash函数f
,它将字符串值s
作为其参数之一。
如果s
不是[1000-9999]
之间的整数,我需要中止执行。
我最初认为我会尝试将字符串转换为int并对结果执行算术范围检查,中止错误,但所有其他参数都使用RegEx检查,因此我可能也是一致的。实际上我必须这样做。
Bash版本:4 +
我无法想出一个比这更好看的模式:
[[ "$s" =~ [[:\<:]][[:digit:]]{4}[[:\>:]] ]]
你能帮助我提高上面模式检查结构的可读性吗?
我在上面的模式中特别不喜欢的是:
<
转义为[[:\<:]]
我的一个想法是使用全线边界检查,虽然这是一个黑客攻击? (即使用^ ... $而不是\ b ... \ b)
(可选) :: Bash中的参数验证是否有相当完善的模式?
答案 0 :(得分:2)
另外,我会尝试:
[[ $s =~ ^[1-9][0-9]{3}$ ]]
否则0999
会通过。但另一方面可能是+1234
可能是有效输入,因此可能是1234.0
,所以如果你需要完成,你可能需要扩展你的正则表达式,或者毕竟执行值检查..
答案 1 :(得分:2)
bash
可以进行整数比较:
shopt -s extglob # Needed for the extended pattern +(...)
f () {
if [[ $1 == +([[:digit:]]) ]] &&
(( $1 >= 1000 && $1 < 10000 )); then
...
fi
}
答案 2 :(得分:1)
请参阅http://mywiki.wooledge.org/BashFAQ/054
你可以只使用模式匹配来做到这一点,但我会拆分它。我会说这样的事情接近于“通常”的方法:
f() {
if [[
$1 == +([[:digit:]]) &&
"$1 >= 1000 && $1 < 10000" -ne 0
]]
then
...
fi
}
在Bash / ksh测试表达式复合命令中,数值比较运算符的参数被计算为算术表达式。双引号允许表达式中的空格,否则解析器无法区分某些算术运算符和测试表达式运算符。测试左侧的表达式0
是否基本等同于(())
。除了只使用一个命令外,这与@ chepner的answer完全相同。我希望这表现得稍好一些,我习惯了语法,所以我很清楚。有些人更喜欢另一种方式。与其他测试结合使用时,您应该只使用[[
算术运算符而不是((
。
在使用任何不可预测的输入作为算术表达式之前,您必须首先进行验证。然后你可以检查它是否在一定范围内。还有其他方法可以做到这一点,但这就是我个人的方式。它很清楚,适用于这个问题的所有排列。
我还应该补充一点,如果您的输入可能包含八进制或十六进制文字,则需要进行一些进一步的处理。在这种情况下,通常通过printf %d
运行输入效果很好。