我想测试一个变量是否超过 4 位数字,如下所示
#!/bin/bash
if [ $input has more than 4 digits ]; then
echo " * Please only 4 digits" >&2
echo""
else
the other option
fi
答案1
如果您关心位数(而不是数值),您可以与 Bash/Ksh/Zsh 中的正则表达式进行匹配(* 请参阅脚注[[:digit:]]
):
#!/bin/bash
input=$1
re='^[[:digit:]]{1,4}$'
if [[ $input =~ $re ]]; then
echo "'$input' contains 1 to 4 digits (and nothing else)"
else
echo "'$input' contains something else"
fi
或者例如[[ $input =~ ^[[:digit:]]{5,}$ ]]
检查“5 个或更多数字(没有其他数字)”等。
或者在纯 POSIX shell 中,您必须使用case
模式匹配:
#!/bin/sh
input=$1
case $input in
*[![:digit:]]*) onlydigits=0;; # contains non-digits
*[[:digit:]]*) onlydigits=1;; # at least one digit
*) onlydigits=0;; # empty
esac
if [ $onlydigits = 0 ]; then
echo "'$input' is empty or contains something other than digits"
elif [ "${#input}" -le 4 ]; then
echo "'$input' contains 1 to 4 digits (and nothing else)"
else
echo "'$input' contains 5 or more digits (but nothing else)"
fi
(你可以把所有的逻辑都放在 里面case
,但是if
在我看来,嵌套 那里 有点难看。)
请注意,[[:digit:]]
应该与当前区域设置的“数字”概念相匹配。这可能会或可能不会超过 ASCII 数字0123456789
。在我的系统上,[[:digit:]]
不匹配例如 ⁴(上标四,U+2074),但是[0-9]
匹配。匹配其他“数字”可能是一个问题,尤其是。如果你对 shell 中的数字进行算术运算。因此,如果您想更严格,请使用[0123456789]
仅接受 ASCII 数字。
答案2
这里假设您仅指 ASCII 十进制数字,而不是其他类型的十进制或非十进制数字。
shopt -s extglob # enables a subset of ksh extended globs including *(...),
# +(...) and ?(...) but unfortunately not {4}(...)
d='[0123456789]' nd='[^0123456789]'
case $input in
( $d$d$d$d+($d) ) echo made of more than 4 digits;;
( *$d*$d*$d*$d*$d* ) echo contains more than 4 digits;;
( "" ) echo empty;;
( *($nd) ) echo does not contain any digit;;
( *$nd* ) echo no more than 4 digits but also contains non-digits;;
( $d?($d)?($d)?($d) ) echo made of 1 to 4 digits;;
( * ) echo should not be reached;;
esac
请注意,根据bash
系统和区域设置,[0-9]
并且[[:digit:]]
可能匹配的不仅仅是 0123456789,因此这些不应该用于输入验证(更多内容请参阅这是对另一个问题的回答例如)。
还要注意的是bash
模式匹配在多字节语言环境中以非常令人惊讶的方式工作。
您会发现,例如在zh_CN.gb18030
中文语言环境中,input='1-©©'
它将按预期返回no more than 4 digits but also contains non-digits
,但如果您附加单个0x80
字节 ( input='1-©©'$'\x80'
),它将返回contains more than 4 digits
。
正是出于这种原因(事实上,模式匹配在许多 shell 的极端情况下都存在错误),对于输入验证,最好对您接受的内容尽可能使用正匹配(而不是负匹配)对于要拒绝的事物) 1 因此,$d?($d)?($d)?($d)
尽管至少在理论上它不是必需的,但其他任何内容都应该与早期的模式相匹配。
1 作为一个例外,人们可能需要考虑 Bourne 和 Korn shell 的缺陷,即case $input in [x]) echo yes; esac
匹配 onx
但也匹配[x]
!
答案3
我会做
#!/usr/bin/env bash
die () { echo "$*" >&2; exit 1; }
input=$1
[[ $input == +([[:digit:]]) ]] || die "only digits please"
(( input <= 9999 )) || die "no more than 4 digits please"
echo "ok: $input"
答案4
这是另一种方式:
#!/bin/bash
if test -z "$1"
then
echo no digit supplied
elif grep -qE '[[:digit:]]{5}' <<< "$1"
then
echo too many digits supplied
else
echo number of digits ok
fi