[/test

[/test

因此,作为 GIT 新手,因此对 bash 命令和脚本非常生疏,我一直在寻找不同的语法和脚本帮助。现在,我找到了很多帮助,并且能够创建脚本和别名,这将使我的 Git 体验更加愉快。

然而,我遇到了一些似乎让我困惑的细微差别,特别是与“if”命令相关的细微差别。

if [ -z $1 ] ; #<- Zero length string
if [[ -z $1 ]] ; #<- Also Zero Length String
if [[ "$1" == -* ]] ; #<- Starts with - (hyphen)


if [ -z $1 ] && [ -z $2 ] ; #<- both param 1 & 2 are zero length
if [[ -z $1 ]] && [[ -z $2 ]] ; #<- Also both param 1 & 2 are zero length
if [[ "$1" == -* ]] || [[ "$2" == -* ]] ; #<- Either param 1 or 2 starts with -

if [ "$1" == -* ] || [ "$2" == -* ] ; #<- Syntax Failure, "bash: ]: too many arguments"

为什么会出现差异?如何知道何时需要 [[(双精度)以及何时需要 [(单精度)?

感谢 Jaeden“Sifo Dyas”al'Raec Ruiner

答案1

首先,请注意,这两种类型的括号都不是 语法的一部分 if。反而:

  • [是内置 shell 的另一个名称test
  • [[ ... ]]是一个单独的内置函数,具有不同的语法和语义。

以下是 bash 文档的摘录:

[/test

test: test [expr]
    Evaluate conditional expression.

    Exits with a status of 0 (true) or 1 (false) depending on
    the evaluation of EXPR.  Expressions may be unary or binary.  Unary
    expressions are often used to examine the status of a file.  There
    are string operators and numeric comparison operators as well.

    The behavior of test depends on the number of arguments.  Read the
    bash manual page for the complete specification.

    File operators:

      -a FILE        True if file exists.
      (...)

[[ ... ]]

[[ ... ]]: [[ expression ]]
    Execute conditional command.

    Returns a status of 0 or 1 depending on the evaluation of the conditional
    expression EXPRESSION.  Expressions are composed of the same primaries used
    by the `test' builtin, and may be combined using the following operators:

      ( EXPRESSION )    Returns the value of EXPRESSION
      ! EXPRESSION              True if EXPRESSION is false; else false
      EXPR1 && EXPR2    True if both EXPR1 and EXPR2 are true; else false
      EXPR1 || EXPR2    True if either EXPR1 or EXPR2 is true; else false

    When the `==' and `!=' operators are used, the string to the right of
    the operator is used as a pattern and pattern matching is performed.
    When the `=~' operator is used, the string to the right of the operator
    is matched as a regular expression.

    The && and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
    determine the expression's value.

    Exit Status:
    0 or 1 depending on value of EXPRESSION.

更简单地说,[需要对 bash 表达式进行正常的处理,引用以避免插值等。因此,测试是否为$foo空字符串或未设置的正确方法是:

[ -z "$foo" ]

或者

[[ -z $foo ]]

在第一种情况下引用很重要,因为设置foo="a b" 然后测试[ -z $foo ]将导致test -z接收两个参数,这是不正确的。

的语言[[ .. ]]是不同的,并且正确地了解变量,这与人们对比 bash 更高级的语言所期望的方式非常相似。因此,它比经典[/更不容易出错test

答案2

请键入man bash并阅读文档。

你会在那里找到的东西:

   if list; then list; [ elif list; then list; ] ... [ else list; ] fi
          The  if  list  is  executed.  If its exit status is zero, the
          then list is executed.  Otherwise, each elif list is executed
          in  turn,  and  if its exit status is zero, the corresponding
          then list is executed and the command completes.   Otherwise,
          the  else  list  is executed, if present.  The exit status is
          the exit status of the last command executed, or zero  if  no
          condition tested true.

这意味着之后if可以有任何命令,并且 bash 只关心该命令的返回值。您在上面使用了两个不同的命令:[[[

   test expr
   [ expr ]
          Return a status of 0 (true) or 1  (false)  depending  on  the
          evaluation of the conditional expression expr.  Each operator
          and operand must be a  separate  argument.   Expressions  are
          composed  of  the primaries described above under CONDITIONAL
          EXPRESSIONS.  test does not accept any options, nor  does  it
          accept  and ignore an argument of -- as signifying the end of
          options. [...]

这是许多 shell 上可用的经典测试。

   [[ expression ]]
          Return  a status of 0 or 1 depending on the evaluation of the
          conditional expression expression.  Expressions are  composed
          of  the  primaries  described below under CONDITIONAL EXPRES‐
          SIONS.  Word splitting and pathname expansion  are  not  per‐
          formed  on  the words between the [[ and ]]; tilde expansion,
          parameter and variable expansion, arithmetic expansion,  com‐
          mand  substitution,  process  substitution, and quote removal
          are performed.  Conditional operators  such  as  -f  must  be
          unquoted to be recognized as primaries.

          When  used  with [[, the < and > operators sort lexicographi‐
          cally using the current locale.

          When the == and != operators are  used,  the  string  to  the
          right  of  the  operator  is considered a pattern and matched
          according to the rules described below under  Pattern  Match‐
          ing,  as  if  the  extglob  shell option were enabled.  The =
          operator is equivalent to ==.  If the  shell  option  nocase‐
          match  is  enabled,  the match is performed without regard to
          the case of alphabetic characters.  The return value is 0  if
          the  string  matches (==) or does not match (!=) the pattern,
          and 1 otherwise.  Any part of the pattern may  be  quoted  to
          force the quoted portion to be matched as a string.

这是 bash 的扩展,含义略有不同。尤其==是定义不同。第一个进行字面比较,而第二个剂量通配符匹配。

答案3

当有疑问时(在 bash 中),总是使用双大括号 ( [[ ]]),因为它们是单大括号的超集,在调用时更容易出现用户错误。

[是 bash 中的内部命令,但在其他环境中可以是/bin/test; 的符号链接。相应的]实际上被忽略了,是为了美观而存在的。 归根结底,if /bin/test -z "$VAR"和是相同的语句(尽管可能会也可能不会以 的名称调用子流程,具体取决于您的环境)。if [ -z "$VAR" ][/bin/test

[[ ]]也是 bash 的内在主义,所以没有子 shell,是 的超集[ ],并且还允许更友好的编写,它只是“做正确的事”,[ ]会爆炸。

http://mywiki.wooledge.org/BashFAQ/031进入一个很多更多详情。

相关内容