Respostas:
A diferença entre [[ … ]]e [ … ]é abordada principalmente no uso de suporte simples ou duplo - bash . Crucialmente, [[ … ]]é uma sintaxe especial, enquanto que [é um nome engraçado para um comando. [[ … ]]tem regras especiais de sintaxe para o que está dentro, [ … ]não.
Com as rugas adicionadas de um curinga, veja como [[ $a == z* ]]é avaliado:
[[ … ]]construção condicional em torno da expressão condicional $a == z*.==operador binário, com os operandos $ae z*.a.==operador: teste se o valor da variável acorresponde ao padrão z*.Veja como [ $a == z* ]é avaliado:
[comando com os argumentos formados por avaliar as palavras $a, ==, z*, ].$apara o valor da variável a.aé a seqüência de 6 caracteres foo b*(obtido por exemplo a='foo b*') e a lista de arquivos no diretório atual é ( bar, baz, qux, zim, zum), então o resultado da expansão é a lista de palavras seguintes: [, foo, bar, baz, ==, zim, zum, ].[com os parâmetros obtidos na etapa anterior.
[comando reclama de um erro de sintaxe e retorna o status 2.Nota: Na [[ $a == z* ]]etapa 3, o valor de anão sofre divisão de palavras e geração de nome de arquivo, porque está em um contexto em que uma única palavra é esperada (o argumento à esquerda do operador condicional ==). Na maioria dos casos, se uma única palavra faz sentido nessa posição, a expansão variável se comporta como entre aspas duplas. No entanto, há uma exceção a essa regra: in [[ abc == $a ]], se o valor de acontiver curingas, aserá comparado com o padrão de curinga. Por exemplo, se o valor de afor, a*então [[ abc == $a ]]é verdadeiro (porque o curinga *proveniente da expansão não citada de $acorrespondências *) enquanto que [[ abc == "$a" ]]é falso (porque o caractere comum*provenientes da expansão citada de $anão corresponde bc). Dentro [[ … ]], aspas duplas não fazer a diferença, exceto no lado direito dos operadores cadeia correspondente ( =, ==, !=e =~).
[é um alias para o testcomando. A versão 6 do Unix possuía um ifcomando, mas a versão 7 (1979) veio com o novo shell Bourne que possuía algumas construções de programação, incluindo a construção if-then-else-elif-fi, e a versão 7 do Unix adicionou um testcomando que executava a maior parte do "testes" que foram executados pelo ifcomando em versões mais antigas.
[foi feito um alias para teste ambos foram criados no shell no Unix System III (1981) . Embora se deva observar que algumas variantes do Unix não possuíam um [comando até muito mais tarde ( até o início dos anos 2000 em alguns BSDs shbaseados no shell Almquist (um testbuilt-in sempre foi incluído no ashcódigo-fonte, mas naqueles BSDs foi inicialmente desativado)).
Observe que testaka [é um comando para fazer "testes"; não há atribuição que esse comando faça; portanto, não há razão para desambiguar entre um operador de atribuição e igualdade, portanto, o operador de igualdade é =. ==é suportado apenas por algumas implementações recentes de [(e é apenas um alias para =).
Como [nada mais é que um comando, ele é analisado da mesma maneira que qualquer outro comando do shell.
Especificamente, no seu exemplo, $aporque não é citado, seria dividido em várias palavras de acordo com as regras usuais de divisão de palavras, e cada palavra passaria pela geração do nome do arquivo, também conhecida como globbing, para resultar em possivelmente mais palavras, cada uma dessas palavras resultando em um argumento separado para o [comando.
Da mesma forma, z*seria expandido para a lista de nomes de arquivos no diretório atual começando com z.
Assim, por exemplo, se $aé b* = x, e há z1, z2, b1e b2arquivos no diretório atual, o [comando teria 9 argumentos: [, b1, b2, =, x, ==, z1, z2e ].
[analisa seus argumentos como uma expressão condicional. Esses 9 argumentos não somam uma expressão condicional válida, portanto, provavelmente retornaria um erro.
A [[ ... ]]construção foi introduzida pelo shell Korn provavelmente por volta de 1988, pois ksh86aem 1987 não o ksh88possuía desde o início.
Além do ksh (todas as implementações), [[...]]também é suportado pelo bash (desde a versão 2.02) e pelo zsh, mas as três implementações são diferentes e há diferenças entre cada versão de um mesmo shell, embora as alterações sejam geralmente compatíveis com versões anteriores (uma exceção notável é o bash =~operador conhecido por quebrar alguns scripts após uma determinada versão quando seu comportamento foi alterado). [[...]]não é especificado pelo POSIX, ou Unix ou Linux (LSB). Ele foi considerado para inclusão algumas vezes, mas não foi incluído, pois a funcionalidade comum suportada pelos shells principais já está coberta pelo [comando e pela case-in-esacconstrução.
Toda a [[ ... ]]construção compõe um comando. Ou seja, ele tem um status de saída (que é seu ativo mais importante, pois é o resultado da avaliação da expressão condicional), você pode canalizá-lo para outro comando (embora não seja útil) e geralmente usá-lo onde quiser use qualquer outro comando (somente dentro do shell, pois é uma construção de shell), mas não é analisado como um comando simples normal. O que está dentro é analisado pelo shell como uma expressão condicional e as regras usuais de divisão de palavras e geração de nome de arquivo se aplicam de maneira diferente.
[[ ... ]]conhece ==desde o início e é equivalente a =1 . Um erro do ksh (e está causando confusão e muitos bugs) é que o operador =e ==não é um operador de igualdade, mas um operador de correspondência de padrões (embora o aspecto de correspondência possa ser desativado com aspas, mas com regras pouco claras que diferem de shell para shell).
No código acima [[ $a == z* ]], o shell analisaria isso em vários tokens em regras semelhantes às usuais, reconhecendo-o como uma comparação de correspondência de padrões, tratado z*como um padrão para corresponder ao conteúdo da avariável.
Geralmente, é mais difícil dar um tiro no pé [[ ... ]]do que com o [comando. Mas algumas regras como
-aor -o(use vários [comandos e os operadores &&e || shell )Torne [confiável com os shells POSIX.
[[...]]em diferentes shells suportam operadores extras, como operadores de -ntcorrespondência regexp ... mas a lista e o comportamento variam de shell para shell e de versão para versão.
Portanto, a menos que você saiba com qual shell e versão mínima seu script será interpretado, provavelmente é mais seguro manter o [comando padrão .
1 Uma exceção: [[...]]foi adicionada ao bash na versão 2.02. Até 2.03onde foi alterado, [[ x = '?' ]]retornaria true enquanto [[ x == '?' ]]retornaria false. A citação não impediu a correspondência de padrões ao usar o =operador nessas versões, mas impediu ao usar ==.
[ '!' = foo -o a = a ]em bashpor exemplo.
ambos são usados para avaliar expressões e [[não funcionará com o shell de registro mais antigo POSIX e [[também suportam correspondência de padrões e regex. exemplo tente estes
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]suporta regexps apenas em algumas versões de alguns shells, assim como algumas versões de [suportam a correspondência de regexp. Para efeito de comparação arithemtic, naqueles conchas que o apoio [[, você prefere escrever(( n == 0 && y == 0))