[vs [[: qual deles usar nos scripts bash? [duplicado]

5

A página do manual do zsh, em sua seção sobre test (também conhecida como [ ), aconselha explicitamente contra o uso, e insta os leitores a usar [[ sempre que possível.

A seção relevante afirma:

The command attempts to implement POSIX and its extensions where these are specified. Unfortunately there are intrinsic ambiguities in the syntax; in particular there is no distinction between test operators and strings that resemble them. The standard attempts to resolve these for small numbers of arguments (up to four); for five or more arguments compatibility cannot be relied on. Users are urged wherever possible to use the '[[' test syntax which does not have these ambiguities.

Acho que me deparei com conselhos parecidos para o bash, mas enquanto examino a página do bash man não consigo encontrar nenhuma recomendação "oficial" lá em qual formulário ( [ ou [[ ) usar. (Talvez eu tenha perdido isso?)

Is there any reason, other than backward compatibility with "older shells", for using [ in a bash script? Or to put it differently, does bash keep [ along with [[ for reasons other than backward compatibility?

    
por kjo 07.03.2013 / 11:51

2 respostas

3

O motivo para preferir [ over [[ , se suficiente, é que [ é mais estável entre as diferentes versões bash.

Veja man bash :

compat31

If set, bash changes its behavior to that of version 3.1 with respect to quoted arguments to the [[ conditional command's =~ operator.

compat32

If set, bash changes its behavior to that of version 3.2 with respect to locale-specific string comparison when using the [[ conditional command's < and > operators. Bash versions prior to bash-4.1 use ASCII collation and strcmp(3); bash-4.1 and later use the current locale's collation sequence and strcoll(3).

compat40

If set, bash changes its behavior to that of version 4.0 with respect to locale-specific string comparison when using the [[ conditional command's < and > operators (see previous item) and the effect of interrupting a command list.

Talvez seja também um pouco mais comum para usuários com ksh background.

Nota sobre o desempenho

'[[' é mais rápido como '['

  • Para uma invocação singular, a diferença de velocidade tem sem impacto comensurável e você deve preferir o '[' builtin.
  • Se você estiver dentro de uma construção de loop maior, você pode pensar em replace '[' with '[['

Para uma medição, você pode usar o seguinte script de comparação

let upperBound=$1
echo "check [,  ${upperBound} iterations"
let i=0
time while [ $i -lt ${upperBound} ] ; do let i++ ; done

echo; echo;
echo "check [[, ${upperBound} iterations"
let i=0
time while [[ $i < ${upperBound} ]] ; do let i++ ; done

Resultado do script de comparação

check [, 1000 iterations

real 0m0.031s
user 0m0.028s
sys 0m0.004s

check [[, 1000 iterations

real 0m0.000s
user 0m0.000s
sys 0m0.000s

    
por 07.03.2013 / 12:05
3

Existem algumas diferenças sutis:

#!/bin/bash

eg=whatever

if [ $eg == what* ]; then   # file glob test
    echo '[]'
fi

if [[ $eg == what* ]]; then   # pattern match test
    echo "[[]]"
fi      

A menos que exista um arquivo chamado "what [something]" no diretório atual, o primeiro teste não passará.

    
por 07.03.2013 / 13:26