如何在shell脚本中有条件地添加标志?

32
我希望在我的bash脚本中运行一个命令,根据环境变量$VERBOSE是否定义来选择是否加上-v标志。就像这样:
```bash if [ -n "$VERBOSE" ]; then mycommand -v else mycommand fi ```
#!/bin/bash

/usr/local/bin/mongo-connector \
  -m $MONGO_HOST \
  -t $NEO_URI \
  [if $VERBOSE then -v ] \
  -stdout
4个回答

43
#!/bin/bash

/usr/local/bin/mongo-connector \
  -m "$MONGO_HOST" \
  -t "$NEO_URI" \
  ${VERBOSE:+-v} \
  -stdout

如果VERBOSE设置为非空值,则${VERBOSE:+-v}将评估为-v。如果VERBOSE未设置或为空,则它将评估为空字符串。请注意,这是您必须避免使用双引号的情况之一。如果您编写:cmd "${VERBOSE:+-v}"而不是cmd ${VERBOSE+:v},则在VERBOSE为空或未设置时,行为在语义上有所不同。在前一种情况下,cmd将被调用一个参数(即空字符串),而在后一种情况下,cmd将被调用零个参数。
要测试VERBOSE是否设置为特定字符串,可以执行以下操作:
/usr/local/bin/mongo-connector \
  -m "$MONGO_HOST" \
  -t "$NEO_URI" \
  $(case ${VERBOSE} in (v1) printf -- '-v foo';; (v2) printf -- '-v bar';; esac )\
  -stdout

但是更清晰的写法似乎是

case "${VERBOSE}" in
v1) varg=foo;;
v2) varg=bar;;
*)  unset varg;;
esac
/usr/local/bin/mongo-connector -m "$MONGO_HOST" -t "$NEO_URI" \
      ${varg+-v "$varg"} -stdout

再次注意此处双引号的使用。您需要将其放在$varg周围以确保只传递一个字符串,并且不想要"${varg+-v "$varg"}",因为您要确保不传递空字符串。此外,由于case语句明确取消了varg,因此现在可以省略:


1
是的,但如何检查$VERBOSE是否设置为特定值?谢谢。 - Alexander Mills
2
如果您想检查特定的值,您需要编写一些明确的比较,例如case语句。没有简单的捷径。 - William Pursell
一个非常简单的例子可能是:[[ ${VERBOSE/A SPECIFIC VALUE/YES} == YES ]] && { 当VERBOSE为“A SPECIFIC VALUE”时的内容; } - Larry

40

为了提高可读性,考虑使用数组来存储参数。

args=(
  -m "$MONGO_HOST"
  -t "$NEO_URI"
  -stdout
)
if [[ -v VERBOSE ]]; then
    args+=(-v)
fi
/usr/local/bin/mongo-connector "${args[@]}"

虽然这可能不是一个问题,但它改变了参数的顺序。 - William Pursell
可以直接保留原始任务中的-stdout,然后在if语句后面添加args+=(-stdout)来解决这个问题。 - chepner

1

这里已经有很好的答案了。还有一个尚未提到的替代方法是直接重新定义您的命令字符串。

#!/bin/bash

CMD=/usr/local/bin/mongo-connector

[[ "$VERBOSE" ]] && CMD="$CMD --verbose"

$CMD \
  -m "$MONGO_HOST" \
  -t "$NEO_URI" \
  -stdout

1
你知道[[ -n "$VERBOSE" ]]或者[[ "$VERSBOSE" ]]与你的否定-z测试是一样的吗? - Jetchisel

1

这似乎有效:

composer dump-autoload $([ "$env" = "production" ] && printf '--classmap-authoritative')

在插入“-n”标志时需要使用“printf -- -n”。 - ruohola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接