检查传递给Bash脚本的参数数

如果未满足所需的参数计数,我希望我的Bash脚本打印一条错误消息。

我尝试了以下代码:

#!/bin/bashecho Script name: $0echo $# argumentsif [$# -ne 1];then echo "illegal number of parameters"fi

由于一些未知的原因,我有以下错误:

test: line 4: [2: command not found

我做错了什么?

1058018 次浏览

就像任何其他简单命令一样,[ ... ]test的参数之间需要空格。

if [ "$#" -ne 1 ]; thenecho "Illegal number of parameters"fi

if test "$#" -ne 1; thenecho "Illegal number of parameters"fi

建议

在Bash中,更喜欢使用[[ ]],因为它不会对其变量进行单词拆分和路径名扩展,除非它是表达式的一部分,否则可能不需要引用。

[[ $# -ne 1 ]]

它还具有一些其他功能,例如未加引号的条件分组、模式匹配(使用extglob进行扩展模式匹配)和正则表达式匹配。

以下示例检查参数是否有效。它允许一个或两个参数。

[[ ($# -eq 1 || ($# -eq 2 && $2 == <glob pattern>)) && $1 =~ <regex pattern> ]]

对于纯算术表达式,使用(( ))到一些可能仍然更好,但它们仍然可以在[[ ]]中使用其算术运算符,如-eq-ne-lt-le-gt-ge,通过将表达式放置为单个字符串参数:

A=1[[ 'A + 1' -eq 2 ]] && echo true  ## Prints true.

如果您还需要将它与[[ ]]的其他功能结合起来,这应该会很有帮助。

请注意,[[ ]](( ))是与ifcasewhilefor具有相同解析级别的关键字。

同样正如戴夫所建议的,错误消息最好发送到stderr,这样当stdout被重定向时就不会包含在内:

echo "Illegal number of parameters" >&2

退出脚本

当向脚本传递无效参数时,使脚本退出也是合乎逻辑的。这已经在评论数 byekangas中提出,但是有人编辑了这个答案,将其与-1作为返回值,所以我不妨做对。

-1虽然被Bash接受为exit的参数,但没有明确记录,并且不适合用作常见建议。64也是最正式的值,因为它是在sysexits.h#define EX_USAGE 64 /* command line usage error */中定义的。大多数工具,如ls,在无效参数时也返回2。我也曾经在脚本中返回2,但最近我不再真正关心,只是在所有错误中使用1。但是让我们把2放在这里,因为它是最常见的,可能不是特定于操作系统的。

if [[ $# -ne 1 ]]; thenecho "Illegal number of parameters" >&2exit 2fi

参考文献

如果你正在处理数字,使用算术表达式可能是个好主意。

if (( $# != 1 )); then>&2 echo "Illegal number of parameters"fi

>&2用于将错误消息写入stderr。

在[]:!=,=,==…是字符串比较运算符,-eq,-gt…是算术二进制运算符。

我会使用:

if [ "$#" != "1" ]; then

或:

if [ $# -eq 1 ]; then

一个简单的一个衬垫,可以使用:

[ "$#" -ne 1 ] && ( usage && exit 1 ) || main

这可以分解为:

  1. 测试bash变量的参数大小$#not等于1(我们的子命令数)
  2. 如果为true,则调用使用()函数并以状态1退出
  3. 否则调用main()函数

注意事项:

  • 使用方法()可以是简单的回显“0美元:参数”
  • main可以是一个长脚本

如果您只对缺少特定参数时的保释感兴趣,那么参数代换很棒:

#!/bin/bash# usage-message.sh
: ${1?"Usage: $0 ARGUMENT"}#  Script exits here if command-line parameter absent,#+ with following error message.#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

您应该在测试条件之间添加空格:

if [ $# -ne 1 ];then echo "illegal number of parameters"fi

我希望这能有所帮助。

如果你想安全起见,我建议使用getopts。

下面是一个小例子:

    while getopts "x:c" opt; docase $opt inc)echo "-$opt was triggered, deploy to ci account" >&2DEPLOY_CI_ACCT="true";;x)echo "-$opt was triggered, Parameter: $OPTARG" >&2CMD_TO_EXEC=${OPTARG};;\?)echo "Invalid option: -$OPTARG" >&2Usageexit 1;;:)echo "Option -$OPTARG requires an argument." >&2Usageexit 1;;esacdone

查看更多详细信息,例如http://wiki.bash-hackers.org/howto/getopts_tutorial

查看这个 bash备忘单,它可以帮助很多。

要检查传入的参数的长度,请使用"$#"

要使用传入的参数数组,请使用"$@"

检查长度和迭代的一个示例是:

myFunc() {if [[ "$#" -gt 0 ]]; thenfor arg in "$@"; doecho $argdonefi}
myFunc "$@"

这篇文章对我有帮助,但对我和我的处境缺少一些东西。希望这能帮助到别人。

这里有一个简单的单行程序来检查是否只给出了一个参数,否则退出脚本:

[ "$#" -ne 1 ] && echo "USAGE $0 <PARAMETER>" && exit

这里有很多好的信息,但我想添加一个我觉得有用的简单片段。

它与上面的一些有什么不同?

  • 将用法打印到stderr,这比打印到stdout更合适
  • 返回另一个回答中提到的退出代码
  • 不会使它成为一个单线…
_usage(){_echoerr "Usage: $0 <args>"}
_echoerr(){echo "$*" >&2}
if [ "$#" -eq 0 ]; then # NOTE: May need to customize this conditional_usageexit 2fimain "$@"