bash bash脚本中的多个`if`语句

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23023326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:10:47  来源:igfitidea点击:

Multiple `if` statements in bash script

bashif-statement

提问by Mark Baker

I'm trying to write a short bash script that optionally accepts arguments from the command line, or prompts for their input

我正在尝试编写一个简短的 bash 脚本,该脚本可选择接受来自命令行的参数,或提示输入

if [ [ -z "$message" ] && [ -z "$predefined" ] ] ; then
  read -p "Enter message [$defaultMessage]: " message
  message=${message:-$defaultMessage}
else
  if [ -n "$predefined" ]; then
    if [ -f $base/$environment/vle/data/$predefined.txt ]; then
      echo Predefined message file $predefined.txt does not exist
      exit 1
    fi
  fi
fi

If neither messagenor predefinedhas been passed in as command line arguments, then the code should prompt for a value for message; otherwise if predefinedhas been passed in as a command line argument, then the script should test for the existence of a file of that name and only continue if the file does exist

如果既没有message也没有predefined作为命令行参数传入,那么代码应该提示输入一个值message;否则,如果predefined已作为命令行参数传入,则脚本应测试该名称的文件是否存在,并且仅在该文件确实存在时才继续

But I'm getting the following error

但我收到以下错误

[: -z: binary operator expected

at the first of those iftests

在这些if测试的第一个

Any help in explaining what's wrong with my syntax for that first ifstatement? Or providing an alternative syntax to achieve the same objectives.

任何帮助解释我的第一个if语句的语法有什么问题?或者提供替代语法来实现相同的目标。

回答by janos

The first ifis not well-formed. This would work:

第一个if不是很好的形式。这会起作用:

if [ -z "$message" ] && [ -z "$predefined" ]; then

or this:

或这个:

if test -z "$message" && test -z "$predefined"; then

or this bash-specific, easy but dirty way:

或者这个 bash 特定的,简单但肮脏的方式:

if [[ -z "$message" ]] && [[ -z "$predefined" ]]; then

or this bash-specific proper way:

或者这个 bash 特定的正确方法:

if [[ -z $message && -z $predefined ]]; then

In this last version the double-quotes are unnecessary, not a typo.

在最后一个版本中,双引号是不必要的,而不是打字错误。

Thanks @mklement0for the corrections in the bash-specific style, and for this final comment:

感谢@mklement0对 bash 特定样式的更正,以及最后的评论:

I should note that there's one case where double-quoting is still a must inside [[ ... ]], namely if you want a variable reference on the right side of a string comparison (==) to be treated as a literal:

v='[a]'
[[ $v == $v ]] # FALSE!
[[ $v == "$v" ]] # true

Without double-quoting, the right-hand side is interpreted as a pattern. Some people advocate always double-quoting variable references so as not to have to remember such subtleties. That said (from bash 3.2 on), you must NOT double-quote the right operand when regex matching with =~

我应该注意到,在一种情况下,双引号仍然是必须的[[ ... ]],即如果您希望将字符串比较 ( ==)右侧的变量引用视为文字:

v='[a]'
[[ $v == $v ]] # FALSE!
[[ $v == "$v" ]] # true

没有双引号,右侧被解释为一个模式。有些人主张总是用双引号引用变量,以免记住这些微妙之处。也就是说(从 bash 3.2 开始),当正则表达式与=~

回答by Keith Reynolds

test expression1 -a expression2

is true if both expressions are true.

如果两个表达式都为真,则为真。

test expression1 -o expression2

is true if either or both expressions are true.

如果一个或两个表达式为真,则为真。

if [ -z "$message" -a -z "$predefined" ]; then
    read -p "Enter message [$defaultMessage]: " message
    message=${message:-$defaultMessage}
else
    if [ -n "$predefined" -a -f $base/$environment/vle/data/$predefined.txt ]; then
        echo Predefined message file $predefined.txt does not exist
        exit 1
    fi
fi

This was able to combine 4 test into 2 while also getting rid of one nested if expression; then ; fi

这能够将 4 个测试合并为 2 个,同时还摆脱了一个嵌套的 if 表达式;然后 ; 菲