888

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

我尝试了以下代码:

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

由于某些未知原因,我收到以下错误:

test: line 4: [2: command not found

我究竟做错了什么?

4

10 回答 10

1355

Just like any other simple command, [ ... ] or test requires spaces between its arguments.

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

Or

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

Suggestions

When in Bash, prefer using [[ ]] instead as it doesn't do word splitting and pathname expansion to its variables that quoting may not be necessary unless it's part of an expression.

[[ $# -ne 1 ]]

It also has some other features like unquoted condition grouping, pattern matching (extended pattern matching with extglob) and regex matching.

The following example checks if arguments are valid. It allows a single argument or two.

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

For pure arithmetic expressions, using (( )) to some may still be better, but they are still possible in [[ ]] with its arithmetic operators like -eq, -ne, -lt, -le, -gt, or -ge by placing the expression as a single string argument:

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

That should be helpful if you would need to combine it with other features of [[ ]] as well.

Take note that [[ ]] and (( )) are keywords which have same level of parsing as if, case, while, and for.

Also as Dave suggested, error messages are better sent to stderr so they don't get included when stdout is redirected:

echo "Illegal number of parameters" >&2

Exiting the script

It's also logical to make the script exit when invalid parameters are passed to it. This has already been suggested in the comments by ekangas but someone edited this answer to have it with -1 as the returned value, so I might as well do it right.

-1 though accepted by Bash as an argument to exit is not explicitly documented and is not right to be used as a common suggestion. 64 is also the most formal value since it's defined in sysexits.h with #define EX_USAGE 64 /* command line usage error */. Most tools like ls also return 2 on invalid arguments. I also used to return 2 in my scripts but lately I no longer really cared, and simply used 1 in all errors. But let's just place 2 here since it's most common and probably not OS-specific.

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

References

于 2013-09-02T08:30:04.767 回答
96

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

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

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

于 2013-12-14T20:50:24.297 回答
44

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

我会使用:

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

或者:

if [ $# -eq 1 ]; then
于 2014-01-07T10:13:26.173 回答
36

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

#!/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
于 2014-10-16T05:32:45.013 回答
15

可以使用以下方法来完成一个简单的工作线:

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

这分解为:

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

注意事项:

  • usage() 可以只是简单的 echo "$0: params"
  • main 可以是一个长脚本
于 2014-08-12T02:38:15.693 回答
11

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

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

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

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

myFunc() {
  if [[ "$#" -gt 0 ]]; then
    for arg in "$@"; do
      echo $arg
    done
  fi
}

myFunc "$@"

这篇文章对我有帮助,但对我和我的情况来说缺少一些东西。希望这可以帮助某人。

于 2019-03-06T16:31:19.290 回答
1

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

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

_usage(){
    _echoerr "Usage: $0 <args>"
}

_echoerr(){
    echo "$*" >&2
}

if [ "$#" -eq 0 ]; then # NOTE: May need to customize this conditional
    _usage
    exit 2
fi
main "$@"

于 2020-07-03T16:56:19.780 回答
1

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

[ "$#" -ne 1 ] && echo "USAGE $0 <PARAMETER>" && exit
于 2019-04-12T08:55:37.563 回答
0

In case you want to be on the safe side, I recommend to use getopts.

Here is a small example:

    while getopts "x:c" opt; do
      case $opt in
        c)
          echo "-$opt was triggered, deploy to ci account" >&2
          DEPLOY_CI_ACCT="true"
          ;;
            x)
              echo "-$opt was triggered, Parameter: $OPTARG" >&2 
              CMD_TO_EXEC=${OPTARG}
              ;;
            \?)
              echo "Invalid option: -$OPTARG" >&2 
              Usage
              exit 1
              ;;
            :)
              echo "Option -$OPTARG requires an argument." >&2 
              Usage
              exit 1
              ;;
          esac
        done

see more details here for example http://wiki.bash-hackers.org/howto/getopts_tutorial

于 2017-11-12T13:15:03.567 回答
-1

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

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

我希望这有帮助。

于 2015-11-19T01:23:51.483 回答