O que você escreveu na verdade quase funciona (funcionaria se todas as variáveis fossem números), mas não é uma maneira idiomática.
(…)
parênteses indicam um subshell . O que há dentro deles não é uma expressão como em muitos outros idiomas. É uma lista de comandos (assim como parênteses externos). Esses comandos são executados em um subprocesso separado, portanto, qualquer redirecionamento, atribuição, etc. realizado dentro dos parênteses não tem efeito fora dos parênteses.
- Com um cifrão à esquerda,
$(…)
é uma substituição de comando : há um comando entre parênteses e a saída do comando é usada como parte da linha de comando (após expansões extras, a menos que a substituição seja entre aspas duplas, mas isso é outra história ) .
{ … }
chaves são como parênteses, pois agrupam comandos, mas apenas influenciam a análise, não o agrupamento. O programa x=2; { x=4; }; echo $x
imprime 4, enquanto que x=2; (x=4); echo $x
imprime 2. (As chaves também exigem espaços ao seu redor e um ponto-e-vírgula antes de fechar, enquanto os parênteses não. Isso é apenas uma peculiaridade de sintaxe.)
- Com um sinal de dólar à frente,
${VAR}
é uma expansão de parâmetro , expandindo para o valor de uma variável, com possíveis transformações extras.
((…))
parênteses duplos cercam uma instrução aritmética , isto é, uma computação em números inteiros, com uma sintaxe semelhante a outras linguagens de programação. Essa sintaxe é usada principalmente para atribuições e em condicionais.
- A mesma sintaxe é usada em expressões aritméticas
$((…))
, que se expandem para o valor inteiro da expressão.
[[ … ]]
colchetes duplos cercam expressões condicionais . Expressões condicionais são construídas principalmente em operadores , como -n $variable
para testar se uma variável está vazia e -e $file
para testar se existe um arquivo. Há também operadores de corda de igualdade: "$string1" == "$string2"
(cuidado que o lado direito é um padrão, por exemplo, [[ $foo == a* ]]
testes se $foo
inicia com a
enquanto [[ $foo == "a*" ]]
testa se $foo
é exatamente a*
), e o familiar !
, &&
e ||
operadores de negação, conjunção e disjunção, bem como parênteses para agrupar. Observe que você precisa de um espaço ao redor de cada operador (por exemplo [[ "$x" == "$y" ]]
, não [[ "$x"=="$y" ]]
) e um espaço ou um caractere como ;
dentro e fora dos colchetes (por exemplo [[ -n $foo ]]
, não[[-n $foo]]
)
[ … ]
colchetes simples são uma forma alternativa de expressões condicionais com mais peculiaridades (mas mais antigas e mais portáteis). Não escreva nenhum por enquanto; comece a se preocupar com eles quando encontrar scripts que os contenham.
Esta é a maneira idiomática de escrever seu teste no bash:
if [[ $varA == 1 && ($varB == "t1" || $varC == "t2") ]]; then
Se você precisar de portabilidade para outros shells, esta seria a maneira (observe as citações adicionais e os conjuntos separados de colchetes em torno de cada teste individual, e o uso do =
operador tradicional em vez da ==
variante ksh / bash / zsh ):
if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then
Gilles 'SO- parar de ser mau'
fonte
==
para diferenciar a comparação de atribuir uma variável (que é também=
)[[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]
que iniciam não iniciam um subprocesso, embora o primeiro marcador diga explicitamente: "O que está entre [parênteses] não é uma expressão como em muitos outros idiomas" - mas certamente está aqui! Provavelmente isso é óbvio para o experiente especialista em bash, mas nem para mim, imediatamente. A confusão pode surgir porque parênteses únicos podem ser usados em umaif
declaração, mas não em expressões entre colchetes duplos.==
não é realmente "mais idiomático" do que=
. Eles têm o mesmo significado, mas==
é uma variante do ksh também disponível no bash e no zsh, enquanto que=
é portátil. Não há realmente nenhuma vantagem em usar==
, e ele não funciona de forma simples.==
dentro[[ … ]]
, se quiser, mas=
tem a vantagem de também trabalhar[ … ]
, por isso recomendo não adotar o hábito de usá==
-lo.muito perto
Deveria trabalhar.
quebrando
é uma comparação inteira onde, como
é uma comparação de cadeias. caso contrário, estou apenas agrupando as comparações corretamente.
Colchetes duplos delimitam uma expressão condicional. E acho que é uma boa leitura sobre o assunto a seguir: "(IBM) Demystify test, [, [[, ((e if-then-else")
fonte
't1'
é desnecessária, certo? Como, em oposição às instruções aritméticas entre parênteses duplos, ondet1
seria uma variável,t1
em uma expressão condicional entre colchetes duplos é apenas uma string literal. Ou seja,[[ $varB == 't1' ]]
é exatamente o mesmo que[[ $varB == t1 ]]
, certo?Uma versão muito portátil (mesmo para o shell bourne herdado):
Isso tem a qualidade adicional de executar apenas um subprocesso no máximo (que é o processo
[
), qualquer que seja o sabor do shell.Substitua
=
por-eq
se as variáveis contiverem valores numéricos, por exemplo3 -eq 03
é verdade, mas3 = 03
é falso. (comparação de cadeias)fonte
Aqui está o código para a versão curta da instrução if-then-else:
Preste atenção ao seguinte:
||
e&&
operandos dentro se condição (ou seja, entre parênteses arredondados) são operandos lógicos (ou / e)||
e&&
operandos fora se condição significa então / elsePraticamente a afirmação diz:
if (a = 1 ou b = 2) então "ok" else "nok"
fonte
( ... )
cria um subshell. Talvez você queira usar chaves{ ... }
. Qualquer estado criado em um subshell não será visível no chamador.fonte