检查 bash 脚本的参数是否为全数字的字符串

检查 bash 脚本的参数是否为全数字的字符串

bash 常见问题解答

如果您要验证一个简单的“数字字符串”,您可以使用 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-1or ./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

相关内容