如果您要验证一个简单的“数字字符串”,您可以使用 glob 来完成:
# Bash
if [[ $foo = *[!0-9]* ]]; then
echo "'$foo' has a non-digit somewhere in it"
else
echo "'$foo' is strictly numeric"
fi
我想,“很好,这看起来又漂亮又简单”。然后我将其完全粘贴到脚本中,除了在第一个 echo 之后添加“exit 1”并更改$foo
为$1
,这样它看起来像
if [[ $1 = *[!0-9]* ]]; then
echo "'$1' has a non-digit somewhere in it"
exit 1
else
echo "'$1' is strictly numeric"
fi
然后我尝试运行这个并得到
$ sh foo.sh bar
bar
foo.sh: 6: [[: not found
'bar' is strictly numeric
我很羞愧地说,我是 Bash 文盲,所以我不知道这里出了什么问题。我有这样的印象,得到了支持在线 Bash 手册与正则表达式匹配的运算符是=~
,但更改它没有任何区别。据我所知,这里似乎有问题的运算符看起来是标准的,尽管我不知道 和 之间有什么区别,它们都对应于测试[[
表达式[[ ]]
。[ ]
我正在使用 Debian squeeze 和 bash
$ bash --version
GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu)
Debian 说的是版本4.1-3
。
答案1
sh
如果那是 bash 脚本,你为什么要调用?很明显,在您的系统上,sh
不是 bash,而是 Bourne/POSIX 系列中的其他一些 shell。事实上,它是短跑,一个较小的 shell,专为低内存消耗和速度而设计,几乎只支持POSIX构造和内置实用程序。
[[ … ]]
是 Bourne 语法的 ksh 扩展,由 bash 和 zsh 采用,但 POSIX 未采用。在可移植脚本中,您需要用于[ … ]
测试。标准构造不支持任何模式匹配;标准习惯用法是使用case
构造:
case $1 in # branch to the first pattern that $1 matches
*[!0-9]*) # pattern = anything containing a non-digit
echo not a number # do this if the first pattern triggered
;; # end of this case branch
*) # pattern = anything (else)
echo successor of $(($1-1)) # do this if the second pattern triggered
;; # end of this case branch
esac # end of the case construct
这是一个测试其参数是否为全数字的函数:
is_all_digits () {
case $1 in *[!0-9]*) false;; esac
}
题外话:我最初在上面的代码片段中犯了一个拼写错误:我写了$(($0-1))
.这导致了看起来很奇怪的错误消息:
$ ash foo.sh 42
foo.sh: 4: arithmetic expression: expecting EOF: "foo.sh-1"
$ ash ./foo.sh 42
./foo.sh: 4: arithmetic expression: expecting primary: "./foo.sh-1"
$ ksh ./foo.sh 42
./foo.sh: line 3: foo.sh: invalid variable name
$ pdksh ./foo.sh 42
./foo.sh[4]: ./foo.sh-1: unexpected `.'
$ bash foo.sh 42
foo.sh: line 3: foo.sh-1: syntax error: invalid arithmetic operator (error token is ".sh-1")
$ bash ./foo.sh 42
./foo.sh: line 3: ./foo.sh-1: syntax error: operand expected (error token is "./foo.sh-1")
$ zsh foo.sh 42
foo.sh:3: bad floating point constant
$0
是脚本的名称,因此要计算的算术表达式是foo.sh-1
or ./foo.sh-1
。您可以观察 shell 之间错误消息的多样性。我有点惊讶地发现 ash 的消息和 bash 的消息没有./
是最清晰的:其他 shell 都没有提到问题出在算术表达式中。 Ash 和 pdksh 确实会因为报告错误一行而获得停靠点。
答案2
尝试使用 运行它bash foo.sh bar
。如果您要编写 bash 脚本,则需要使用 bash。上面使用的 [[ 和 ]] 仅在 bash 中,bash 是 Bourne shell 的衍生版本。 sh 表示 Bourne SHell,可能与 bash 不同。我认为 Debian 使用 dash 来表示 sh。如果您想学习如何编写不需要 bash 特定功能的可移植 Bourne shell 脚本,您可以使用 grep 重写:
if echo "$foo" | grep '^[0-9][0-9]*$' >/dev/null 2>&1; then
echo "'$1' has a non-digit somewhere in it"
exit 1
else
echo "'$1' is strictly numeric"
fi
答案3
我建议使用expr
因为它符合 POSIX 标准:
if [ "$(expr "$1" : '^[0-9]\+$')" = "0" ]; then
echo "'$1' has a non-digit somewhere in it"
exit 1
else
echo "'$1' is strictly numeric"
fi