Bash - Se confusão de sintaxe

3

Então, Sendo novo no GIT e, portanto, extremamente enferrujado em meus comandos e scripts bash, estive procurando por uma sintaxe e uma ajuda de script diferentes. Agora, encontrei muita ajuda e consegui criar os scripts e alias que tornarão minha experiência no Git mais agradável.

No entanto, me deparei com algumas nuances que parecem me confundir, especificamente relacionadas ao comando "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"

Por que a discrepância? Como saber quando o [[(double) é necessário e quando um [(single) será necessário?

Obrigado Jaeden "Sifo Dyas" al'Raec Ruiner

    
por JaedenRuiner 08.12.2015 / 19:41

3 respostas

8

Em primeiro lugar, observe que nenhum dos tipos de colchetes faz parte da sintaxe %código%. Em vez disso:

  • if é outro nome para o shell embutido [ ;
  • test é um built-in separado, com sintaxe e semântica diferente.

Aqui estão trechos da documentação do bash:

[[ ... ]] / [

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.
      (...)

test

[[ ... ]]: [[ 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.

Mais simplesmente dito, [[ ... ]] requer que se tome o cuidado normal necessário para expressões bash, citar para evitar a interpolação, etc. de testar se [ é a string vazia ou se não está definida, seria:

[ -z "$foo" ]

ou

[[ -z $foo ]]

É importante citar no primeiro caso, porque a configuração $foo e, em seguida, testar foo="a b" resultaria em [ -z $foo ] recebendo dois argumentos, o que é incorreto.

O idioma para test -z é diferente e sabe bem sobre variáveis, muito do modo que se esperaria de um nível mais alto linguagem do que bash. Por esta razão, é muito menos propenso a erros do que clássico [[ .. ]] / [ .

    
por 08.12.2015 / 19:49
1

Por favor, digite man bash e leia a documentação.

Coisas que você vai encontrar lá:

   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.

Isso significa que após if pode haver qualquer comando e o bash só se preocupa com o valor de retorno desse comando. Você usou dois comandos diferentes acima: [ e [[ .

   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. [...]

Este é o teste clássico disponível em muitos shells.

   [[ 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.

Esta é uma extensão no bash com um significado ligeiramente diferente. Especialmente == é definido de forma diferente. O primeiro faz uma comparação literal, enquanto o segundo combinações de curingas de dose.

    
por 08.12.2015 / 19:58
-1

Em caso de dúvida (e no bash), sempre usa chaves duplas ( [[ ]] ), pois são um superconjunto das chaves simples que são mais propensas a erros do usuário em sua invocação .

[ é um comando interno no bash, mas em outros ambientes pode ser um symlink para /bin/test ; o ] correspondente é realmente ignorado e está lá para a estética. if /bin/test -z "$VAR" e if [ -z "$VAR" ] são declarações idênticas, no final do dia (apesar de [ poder ou não invocar um subprocesso em nome de /bin/test , dependendo do seu ambiente).

[[ ]] é também um internalismo para o bash, então não há subshell, é um superconjunto de [ ] e também permite uma escrita mais amigável, que apenas faz a coisa certa, onde [ ] iria explodir.

link entra em lote mais detalhes.

    
por 08.12.2015 / 19:56

Tags