如何编写带有或不带有参数的脚本?

如何编写带有或不带有参数的脚本?

我有一个 bash 脚本,其内容如下:

#!/bin/bash

if [ $1 = "--test" ] || [ $1 = "-t" ]; then
    echo "Testing..."
    testing="y"

else
    testing="n"
    echo "Not testing."

fi

因此,我想要做的不仅是使用 或 来运行它./script --test./script -t而且可以使用任何参数(仅./script)来运行它,但似乎如果我使用当前代码执行此操作,则输出仅为:

./script: line 3: [: =: unary operator expected
./script: line 3: [: =: unary operator expected
Not testing.

那么我该如何编程才能让它在没有任何参数的情况下运行而不会else抛出错误?我做错了什么?

答案1

有几种方法;最明显的两种是:

  • 放入$1双引号中:if [ "$1" = "--test" ]
  • 使用 $# 检查参数数量

更好的是,使用 getopts。

答案2

您需要在 if 条件中引用变量。替换:

if [ $1 = "--test" ] || [ $1 = "-t" ]; then

和:

if [ "$1" = '--test' ] || [ "$1" = '-t' ]; then  

然后它就可以工作了:

➜ ~ ./test.sh
未测试。

始终对变量使用双引号!

答案3

您正在使用 bash。Bash 有一个很好的替代方案[[[。使用[[,您不必担心是否引用,并且您会获得比更多的运算符[,包括对的适当支持||

if [[ $1 = "--test" || $1 = "-t" ]]
then
    echo "Testing..."
    testing="y"
else
    testing="n"
    echo "Not testing."
fi

或者您可以使用正则表达式:

if [[ $1 =~ ^(--test|-t) ]]
then
    echo "Testing..."
    testing="y"
else
    testing="n"
    echo "Not testing."
fi

[当然,始终应该进行正确的引用,但是在使用 bash 时没有理由坚持这样做。

答案4

在 shell 脚本中使用长选项的“正确方法”是通过getopt GNU 实用程序. 还有getopts 是 bash 内置的,但它只允许使用短选项,例如。可以找到-t一些使用示例getopt这里

这是一个脚本,演示了我如何处理您的问题。大多数步骤的解释都作为注释添加到脚本本身中。

#!/bin/bash

# GNU getopt allows long options. Letters in -o correspond to
# comma-separated list given in --long.

opts=$(getopt -o t --long test -- "$*")
test $? -ne 0 && exit 2 # error happened

set -- $opts # some would prefer using eval set -- "$opts"
# if theres -- as first argument, the script is called without
# option flags
if [ "$1" = "--"  ]; then
    echo "Not testing"
    testing="n"
    # Here we exit, and avoid ever getting to argument parsing loop
    # A more practical case would be to call a function here
    # that performs for no options case
    exit 1
fi

# Although this question asks only for one 
# option flag, the proper use of getopt is with while loop
# That's why it's done so - to show proper form.
while true; do
    case "$1" in
        # spaces are important in the case definition
        -t | --test ) testing="y"; echo "Testing" ;;
    esac
    # Loop will terminate if there's no more  
    # positional parameters to shift
    shift  || break
done

echo "Out of loop"

经过一些简化和删除注释,可以将其浓缩为:

#!/bin/bash
opts=$(getopt -o t --long test -- "$*")
test $? -ne 0 && exit 2 # error happened
set -- $opts    
case "$1" in
    -t | --test ) testing="y"; echo "Testing";;
    --) testing="n"; echo "Not testing";;
esac

相关内容