这是测试数字的正确方法吗,在正则表达式周围使用双[[]]
引号:digit:
和单引号?
if [[ "$var" =~ '^[[:digit:]]+$' ]]; then
答案1
事实并非如此,一个简单的测试将向我们展示:
#!/bin/bash
for var in 1 2 3 a b c; do
if [[ "$var" =~ '^[[:digit:]]+$' ]]; then
echo "$var is a number"
else
echo "$var is NOT a number"
fi
done
运行上面的命令会产生:
1 is NOT a number
2 is NOT a number
3 is NOT a number
a is NOT a number
b is NOT a number
c is NOT a number
如果您有一个自动运行的编辑器shellcheck
,或者您将代码粘贴到https://shellcheck.net/,您将看到以下错误:
Line 4:
if [[ "$var" =~ '^[[:digit:]]+$' ]]; then
^-- SC2076 (warning): Remove quotes from right-hand side of =~ to match as a regex rather than literally.
这告诉我们我们应该这样写:
#!/bin/bash
for var in 1 2 3 a b c; do
if [[ "$var" =~ ^[[:digit:]]+$ ]]; then
echo "$var is a number"
else
echo "$var is NOT a number"
fi
done
其产生:
1 is a number
2 is a number
3 is a number
a is NOT a number
b is NOT a number
c is NOT a number
这记录在bash 手册页:
还可以使用附加二元运算符 =~,其优先级与 == 和 != 相同。使用时,运算符右侧的字符串被视为 POSIX 扩展正则表达式并进行相应的匹配...如果模式的任何部分被引用,则引用的部分将按字面匹配。这意味着引用部分中的每个字符都与其自身匹配,而不具有任何特殊的模式匹配含义。
答案2
取决于你所说的数字是什么意思。0x12
, inf
, 1.2
, -12
, ¹²³
, ⑱
, 1e6
, 1,000,000
, , Ⅷ
, 0x123p-5
, 6,23
都是0b100110
根据某些定义的数字数字、 和08
、019
、9999999999999999999999999999999999
是其他一些人的无效数字。
要测试字符串是否由一个或多个 ASCII 十进制数字组成,可以使用:
标准:
valid() {
case $1 in
("" | *[!0123456789]*) false;;
(*) true;;
esac
}
或者在 ksh、bash(bash -O extglob
使用旧版本)中或zsh -o kshglob
:
valid() [[ $1 = +([0123456789]) ]]
或者在 bash/ksh93/zsh/yash 中:
valid() [[ $1 =~ ^[0123456789]+$ ]]
valid() [[ $1 =~ '^[0123456789]+$' ]]
也可以在 zsh1 和 bash 3.1 或bash -O compat31
.在 中zsh
,如果rematchpcre
启用了该选项,您需要将其更改为[[ $1 =~ '^[0123456789]\z' ]]
在$
主题末尾的 PCRE 匹配中,但也在主题末尾的换行符之前,以便例如匹配 on $'123\n'
。到时候你也可以用[[ $1 =~ '^\d+\z' ]]
。
在zsh
:
valid() [[ $1 = <-> ]]
无论如何,请避免[[:digit:]]
在某些系统上与 ASCII 阿拉伯数字以外的十进制数字匹配。除了在 zsh 中,特别是在 bash 中,不要用于[0-9]
输入验证,因为它通常匹配恰好在 0 到 9 之间排序的随机字符。
1 但请注意,在 zsh 中,变量值可以包含 NUL 字节,并且标准 regexp API(与 PCRE 相对)不支持匹配其中包含 NUL 的字符串。当该rematchpcre
选项未启用时,[[ $1 =~ '^[0123456789]+$' ]]
将匹配$'123\0xyz'
例如。