![如何编写带有或不带有参数的脚本?](https://linux22.com/image/990798/%E5%A6%82%E4%BD%95%E7%BC%96%E5%86%99%E5%B8%A6%E6%9C%89%E6%88%96%E4%B8%8D%E5%B8%A6%E6%9C%89%E5%8F%82%E6%95%B0%E7%9A%84%E8%84%9A%E6%9C%AC%EF%BC%9F.png)
我有一个 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