检查Bash Shell脚本中输入参数的存在


1335

我需要检查输入参数的存在。我有以下脚本

if [ "$1" -gt "-1" ]
  then echo hi
fi

我懂了

[: : integer expression expected

如何首先检查输入参数1是否存在?

Answers:


2328

它是:

if [ $# -eq 0 ]
  then
    echo "No arguments supplied"
fi

$#变量将告诉您脚本传递的输入参数的数量。

或者您可以检查参数是否为空字符串,例如:

if [ -z "$1" ]
  then
    echo "No argument supplied"
fi

-z开关是检验的“$ 1”的扩张是一个空字符串或没有。如果为空字符串,则执行主体。


62
我喜欢以简洁的语法这样做,并且仍然可以接受POSIX。[ -z "$1" ] && echo "No argument supplied" 我更喜欢单线,因为它们对我来说更容易。与使用if
JM Becker 2012年

168
exit 1当脚本需要参数时,您可能想在if块的回显末尾添加一个。显而易见,但值得注意的是完整性。
msanford

16
尽管很少有用,但可以初始化第一个参数但为空;programname "" secondarg third。该$#检查明确检查参数的数量。
2013年

39
对于菜鸟来说,尤其是来自非脚本背景的人,提到这些东西的一些特殊性也很重要。您可能还提到过,在开括号和闭括号之后需要一个空格。否则,事情将无法进行。我自己是一个脚本新手(我来自C背景),发现它很困难。只有当我决定“按原样”复制整个内容时,这些内容才对我有用。那时我意识到我必须在开括号之后和闭括号之前留一个空间。
HighOnMeat 2013年

72
和可选的argsif [ ! -z "$1" ]; then ...
gcb 2014年


103

在某些情况下,您需要检查用户是否向脚本传递了参数,如果没有,则返回默认值。就像下面的脚本一样:

scale=${2:-1}
emulator @$1 -scale $scale

在这里,如果用户尚未scale作为第二个参数传递-scale 1,则默认情况下会启动Android模拟器。${varname:-word}是扩展运算符。还有其他扩展运算符:

  • ${varname:=word}其中设置了未定义varname而不是返回的word值;
  • ${varname:?message}它要么返回(varname如果已定义)并且不为null,要么输出message并中止脚本(如第一个示例);
  • ${varname:+word}返回word仅当varname被定义并且不为空; 否则返回null。

1
上面的示例似乎使用${varname?message}。是多余:的打字错误,还是会改变行为?
Eki

6
Eki,在此示例中,“:”是内置命令和/ bin / true的简写。它表示什么都不做的命令,基本上会忽略所提供的参数。为了防止解释器尝试执行“ $ varname”(您当然不希望发生)的内容,此测试至关重要。还值得注意的是;您可以根据需要使用此方法测试尽可能多的变量。并带有特定的错误消息。即: ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
user.friendly

48

尝试:

 #!/bin/bash
 if [ "$#" -eq  "0" ]
   then
     echo "No arguments supplied"
 else
     echo "Hello world"
 fi

4
为什么需要双引号$#0
user13107 2014年

1
没问题,如果我们使用不带双引号的$#和0
Ranjithkumar T

在Windows上,mingw这是唯一的方法。
Lajos Meszaros 2015年

2
这个答案为我刚编写的脚本提供了一个很好的起点。也感谢您展示else
克里斯·K

2
bash中的@ user13107双引号变量可防止乱序(例如foo*,扩展文件名,如)和单词拆分(即,如果值包含空格,则拆分内容)。在这种情况下,不必引用,$#因为这两种情况都不适用。用引号0也不是必需的,但是有些人喜欢用引号,因为它们实际上是字符串,这使它更明确。
丹尼斯

39

检测参数是否传递到脚本的另一种方法:

((!$#)) && echo No arguments supplied!

请注意,这(( expr ))会使表达式根据Shell Arithmetic的规则求值。

为了在没有任何参数的情况下退出,可以说:

((!$#)) && echo No arguments supplied! && exit 1

上面的另一种(类似)表达方式是:

let $# || echo No arguments supplied

let $# || { echo No arguments supplied; exit 1; }  # Exit if no arguments!

help let 说:

let: let arg [arg ...]

  Evaluate arithmetic expressions.

  ...

  Exit Status:
  If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.

2
-1如果验证一个参数的存在,这可能是最糟糕的方法。此外,它还可以触发历史记录替换并可能做坏事。
user.friendly

2
而不是exit杀死我的zsh进程,而是使用return不杀死zsh进程
Timo

为什么会((!$#))触发历史记录替换?
Zhro

25

我经常将此代码段用于简单的脚本:

#!/bin/bash

if [ -z "$1" ]; then
    echo -e "\nPlease call '$0 <argument>' to run this command!\n"
    exit 1
fi

1
那么,这仅在您需要一个参数时使用?
Danijel

21

只是因为有更多要指出的要点,我要补充一点,您可以简单地测试您的字符串是否为空:

if [ "$1" ]; then
  echo yes
else
  echo no
fi

同样,如果您期望arg计数,只需测试最后一个:

if [ "$3" ]; then
  echo has args correct or not
else
  echo fixme
fi

等等与任何arg或var


4

如果要检查参数是否存在,可以检查参数#是否大于或等于目标参数编号。

以下脚本演示了它是如何工作的

test.sh

#!/usr/bin/env bash

if [ $# -ge 3 ]
then
  echo script has at least 3 arguments
fi

产生以下输出

$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments

3

作为一个小提醒,数字测试运营商猛砸只在整数的工作(-eq-lt-ge等)

我想确保我的$ vars是整数

var=$(( var + 0 ))

在测试它们之前,只是为了防止出现[[:必需的整数arg]错误。


1
巧妙的方法,但请注意:由于bash无法处理算术浮点数,因此此方法可能会导致语法错误并返回非零值,这将在启用errexit时造成障碍。 var=$(printf "%.0f" "$var")可以处理浮点数,但在给定字符串时会遭受非零退出。如果您不介意awk,那么我使用的这种方法似乎是强制执行整数的最可靠方法:var=$(<<<"$var" awk '{printf "%.0f", $0}')。如果未设置var,则默认为“ 0”。如果var是浮点型,则将其舍入为最接近的整数。负值也可以使用。
user.friendly

0

一班班轮bash功能验证

myFunction() {

    : ${1?"forgot to supply an argument"}
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

添加函数名称和用法

myFunction() {

    : ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage:  ${FUNCNAME[0]} some_integer"}
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

添加验证以检查整数

要添加其他验证,例如检查传递的参数是否为整数,请修改验证一个内衬以调用验证函数:

: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage:  ${FUNCNAME[0]} some_integer"} && validateIntegers $1 || die "Must supply an integer!"

然后,构造一个验证函数以验证参数,成功时返回0,失败时返回1,而die函数在失败时中止脚本

validateIntegers() {

    if ! [[ "$1" =~ ^[0-9]+$ ]]; then
        return 1 # failure
    fi
    return 0 #success

}

die() { echo "$*" 1>&2 ; exit 1; }

更简单-只需使用 set -u

set -u 确保每个引用的变量在使用时都已设置,因此只需对其进行设置并忘记它

myFunction() {
    set -u
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.