Um colega de trabalho afirmou recentemente em uma revisão de código que a [[ ]]
construção deve ser preferida [ ]
em construções como
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
Ele não conseguiu fornecer uma justificativa. Existe um?
bash
if-statement
syntax
Leonard
fonte
fonte
[[
isso, o código é bom e claro, mas lembre-se daquele dia em que você portará seu scriptworks no sistema com o shell padrão que não ébash
ouksh
, etc.[
é mais feio, pesado, mas funciona comoAK-47
em qualquer situação.Respostas:
[[
tem menos surpresas e geralmente é mais seguro de usar. Mas não é portátil - o POSIX não especifica o que faz e apenas alguns shells o suportam (além do bash, ouvi dizer que o ksh também o suporta). Por exemplo, você pode fazerpara testar se existe um arquivo. Mas com
[
, você tem que citar$b
, porque divide o argumento e expande coisas como"a*"
(onde o[[
leva literalmente). Isso também tem a ver com como[
pode ser um programa externo e recebe seu argumento normalmente como qualquer outro programa (embora também possa ser um componente interno, mas ainda não tenha esse tratamento especial).[[
também possui outros recursos interessantes, como correspondência de expressões regulares=~
e operadores, como eles são conhecidos em idiomas do tipo C. Aqui está uma boa página: Qual é a diferença entre test[
e[[
? e testes de bashfonte
[[ ]]
mas interpreta como o mesmo significado[ ]
.#!/bin/sh
mas depois os alterno para uso#!/bin/bash
assim que confio em algum recurso específico do BASH, para indicar que ele não é mais portátil do shell Bourne.Diferenças de comportamento
Algumas diferenças no Bash 4.3.11:
Extensão POSIX vs Bash:
[
é POSIX[[
é uma extensão do Bash ¹comando regular vs magia
[
é apenas um comando regular com um nome estranho.]
é apenas um argumento[
que impede que outros argumentos sejam usados.O Ubuntu 16.04, na verdade, tem um executável
/usr/bin/[
fornecido pelo coreutils , mas a versão interna do bash tem precedência.Nada é alterado na maneira como Bash analisa o comando.
Em particular,
<
é o redirecionamento&&
e||
concatena vários comandos,( )
gera sub-conchas, a menos que seja escapado\
, e a expansão de palavras acontece normalmente.[[ X ]]
é uma construção única que faz com queX
seja analisado magicamente.<
,&&
,||
E()
são tratados de maneira especial, e regras de decomposição palavra são diferentes.Existem também outras diferenças como
=
e=~
.No Bashese:
[
é um comando interno e[[
é uma palavra-chave: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword<
[[ a < b ]]
: comparação lexicográfica[ a \< b ]
: O mesmo que acima.\
necessário ou o redirecionamento é semelhante a qualquer outro comando. Extensão Bash.expr a \< b > /dev/null
: Equivalente POSIX², consulte: Como testar seqüências lexicográficas menores ou iguais no Bash?&&
e||
[[ a = a && b = b ]]
: verdadeiro, lógico e[ a = a && b = b ]
: erro de sintaxe,&&
analisado como um separador de comandos ANDcmd1 && cmd2
[ a = a -a b = b ]
: equivalente, mas reprovado pelo POSIX³[ a = a ] && [ b = b ]
: POSIX e equivalente confiável(
[[ (a = a || a = b) && a = b ]]
: false[ ( a = a ) ]
: erro de sintaxe,()
é interpretado como um subshell[ \( a = a -o a = b \) -a a = b ]
: equivalente, mas()
foi descontinuado pelo POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]
Equivalente ao POSIX⁵divisão de palavras e geração de nome de arquivo após expansões (divisão + glob)
x='a b'; [[ $x = 'a b' ]]
: true, aspas não necessáriasx='a b'; [ $x = 'a b' ]
: erro de sintaxe, expande para[ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: erro de sintaxe se houver mais de um arquivo no diretório atual.x='a b'; [ "$x" = 'a b' ]
: Equivalente POSIX=
[[ ab = a? ]]
: true, porque faz a correspondência de padrões (* ? [
são mágicos). Não é expandido para arquivos no diretório atual.[ ab = a? ]
:a?
glob se expande. Portanto, pode ser verdadeiro ou falso, dependendo dos arquivos no diretório atual.[ ab = a\? ]
: expansão falsa, não global=
e==
são iguais em ambos[
e[[
, mas==
é uma extensão do Bash.case ab in (a?) echo match; esac
: Equivalente POSIX[[ ab =~ 'ab?' ]]
: false⁴, perde mágica com''
[[ ab? =~ 'ab?' ]]
: verdade=~
[[ ab =~ ab? ]]
: true, correspondência de expressão regular estendida POSIX ,?
não expande glob[ a =~ a ]
: erro de sintaxe. Nenhum equivalente do bash.printf 'ab\n' | grep -Eq 'ab?'
: Equivalente ao POSIX (apenas dados de linha única)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: Equivalente POSIX.Recomendação : use sempre
[]
.Existem equivalentes POSIX para cada
[[ ]]
construção que eu já vi.Se você usa
[[ ]]
você:[
é apenas um comando regular com um nome estranho, sem semântica especial envolvida.¹ Inspirado na
[[...]]
construção equivalente no shell Korn² mas falha em alguns valores de
a
oub
(como+
ouindex
) e faz comparação numérica sea
e seb
parecem com números inteiros decimais.expr "x$a" '<' "x$b"
trabalha em torno de ambos.³ e também falha para alguns valores de
a
oub
como!
ou(
.Bas no bash 3.2 e superior e a compatibilidade fornecida com o bash 3.1 não está ativada (como com
BASH_COMPAT=3.1
)⁵ embora o agrupamento (aqui com o
{...;}
grupo de comandos em vez de(...)
executar um subshell desnecessário) não seja necessário, pois os operadores||
e&&
shell (em oposição aos operadores||
e&&
[[...]]
ou-o
/-a
[
operadores) têm igual precedência. Então[ a = a ] || [ a = b ] && [ a = b ]
seria equivalente.fonte
[
pelos mesmos motivos.[[ ]]
possui mais recursos - sugiro que você dê uma olhada no Advanced Bash Scripting Guide para obter mais informações, especificamente a seção de comando de teste estendido no Capítulo 7. Testes .Aliás, como o guia observa,
[[ ]]
foi introduzido no ksh88 (a versão de 1988 do shell Korn).fonte
De Qual comparador, teste, suporte ou suporte duplo, é o mais rápido? ( http://bashcurescancer.com )
fonte
[[
possa trazer. Mas então, eu sou um peido velho da velha escola :-)[
etest
, embora existam versões externas.PS1=...crazy stuff...
e / ou$PROMPT_COMMAND
); para estes, não quero nenhum atraso perceptível na execução do script.apt-get update
se já faz mais de X horas desde a última execução. É um grande alívio quando se pode deixar a portabilidade fora da lista já muito longa de restrições de código.Se você gosta de seguir o guia de estilo do Google :
Teste
[
e[[
fonte
[[ -d ~ ]]
retorna verdadeiro (o que implica que~
foi expandido para/home/user
). Eu acho que o Google deveria ter sido mais preciso na sua escrita.Uma situação típica em que você não pode usar
[[
está no script autotools configure.ac; os colchetes têm um significado especial e diferente; portanto, você precisará usar emtest
vez de[
ou[[
- Observe esse teste e[
é o mesmo programa.fonte
[
ser definido como uma função de shell POSIX?[[]] colchetes duplos não são suportados em determinadas versões do SunOS e declarações de funções internas totalmente sem suporte por: GNU bash, versão 2.02.0 (1) -release (sparc-sun-solaris2.6)
fonte
Em poucas palavras, [[é melhor porque não bifurca outro processo. Nenhum suporte ou um suporte único é mais lento que um suporte duplo, porque bifurca outro processo.
fonte
type [
para ver isso.[[
, diferentemente de[
, é sintaxe interpretada pelo interpretador de linha de comando bash. No bash, tente digitartype [[
. O unix4linux está correto que, embora os[
testes clássicos do Bourne-shell iniciem um novo processo para determinar o valor verdadeiro, a[[
sintaxe (emprestada do ksh pelo bash, zsh, etc.) não.[
está embutido no Bash e no Dash (/bin/sh
em todas as distribuições Linux derivadas do Debian).