Autor Tópico: Dúvidas sobre o if (bash)  (Lida 10609 vezes)

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Dúvidas sobre o if (bash)
« Online: 25 de Fevereiro de 2015, 08:09 »
Galera, gostaria de saber porque o if tem que ser assim:
Código: [Selecionar]
if [ "$a" = "0" ]; then  echo 'oi'; fi;
Mas não pode ser de uma das três maneiras a seguir:
 if [ $a = "9" ]; then  echo 'oi'; fi;     -> $a pra mim seria um número e "$a" seria a string '$a'
 if ["$a"="9"]; then  echo 'oi'; fi;     -> já que tem que estar entre aspas, porque não posso deixar tudo junto, tem que estar espaçado?
« Última modificação: 01 de MAR?O de 2015, 16:02 por rudregues »
Gentoo — Controle total sobre o sistema.

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Dúvidas sobre o if (bash)
« Resposta #1 Online: 25 de Fevereiro de 2015, 08:51 »
if ["$a"="9"]; then  echo 'oi'; fi;     -> já que tem que estar entre aspas, porque não posso deixar tudo junto, tem que estar espaçado?

Depois de uma boa pesquisa, descobri porque tem que ser separado: o argumento entre colchetes é uma lista. Ou seja, fica if [ lista ], neste caso a lista precisa ter cada um dos argumentos executados e comparados separadamente, se juntar é como se fosse um comando só. Mas obviamente se eu juntar "$a"="9" não é um comando, porém "$a" é um comando e "9" é outro.

Mas ainda não entendi porque precisa ser "$a" ao invés de $a
Gentoo — Controle total sobre o sistema.

Offline byjav

  • Usuário Ubuntu
  • *
  • Mensagens: 11
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #2 Online: 25 de Fevereiro de 2015, 13:09 »
Senão, o valor do variável podia ter espaços que seriam encarados como delimitadores de comandos. Por exemplo,
Código: [Selecionar]
$ if [ "-n foo -a 0" = 0 ]; then echo sim; else echo não; fi
não
porque o if testa se a cadeia "-n foo -a 0" é igual à cadeia "0", enquanto
Código: [Selecionar]
$ if [ -n foo -a 0 = 0 ]; then echo sim; else echo não; fi
sim
porque o if testa se a cadeia "-n" não é vazia e que no mesmo tempo a cadeia "0" é igual à cadeia "0". Então, se o variável a tiver o valor de "-n foo -a 0" e não houver aspas, o resultado será inesperado.

Offline irtigor

  • Equipe Ubuntu
  • Usuário Ubuntu
  • *****
  • Mensagens: 4.344
  • Delete, delete, delete!
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #3 Online: 25 de Fevereiro de 2015, 13:49 »
Mais ou menos certo, mas totalmente errado.

Código: [Selecionar]
a=0
if [ $a = "0" ]; then  echo 'oi'; fi;
if [ "$a" = "0" ]; then  echo 'oi'; fi;

Ambos vão funcionar, mas tem que ficar atento, porque o "=" serve somente pra comparações de strings. Para comparações aritméticas, o equivalente é o "-eq" ("[" é o comando test, "$(which [) --help" ).

Agora o ultimo realmente não vai funcionar nunca, isso porque "[" , assim como o "echo" e outros, historicamente são programas que hoje em dia estão embutidos na maioria do shells ("type ["). Então existe o programa "[", que aceita alguns argumentos, e espera como o ultimo deles um "]". Isso cria limitações, "[qualquer_coisa" não vai ser encontrado no $PATH (porque o nome do programa é só "["), e sem um espaço entre qualquer_coisa e "]", o ultimo argumento não vai ser "]" e sim "qualquer_coisa]". Quando embutiram esse programa nos shells, essas limitações foram mantidas "artificialmente", pra ter compatibilidade com o programa original.

Offline byjav

  • Usuário Ubuntu
  • *
  • Mensagens: 11
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #4 Online: 25 de Fevereiro de 2015, 14:43 »
Código: [Selecionar]
$ a="-n foo -a 0"
$ if [ "$a" = 0 ]; then echo sim; else echo não; fi
não
$ if [ $a = 0 ]; then echo sim; else echo não; fi
sim

Tudo funciona perfeitamente, só é preciso compreender o que se passa. :)

Offline irtigor

  • Equipe Ubuntu
  • Usuário Ubuntu
  • *****
  • Mensagens: 4.344
  • Delete, delete, delete!
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #5 Online: 25 de Fevereiro de 2015, 16:08 »
Por isso você está mais ou menos certo, mas completamente errado. O segundo if está correto, mas não é recomendado, e a sua mensagem também não explicava o porque do espaço depois do [ e antes do ], ou da não diferença entre "$a" e $a quanto ao tipo.

Offline byjav

  • Usuário Ubuntu
  • *
  • Mensagens: 11
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #6 Online: 25 de Fevereiro de 2015, 18:36 »
Então acha que há erros. O que é, precisamente, que escrevi falso?

Ao contrário, eu afirmo que não é correcto dizer que «ambos vão funcionar». Como já demonstrei, os resultados podem ser diferentes. Além disso, a versão sem aspas pode acabar com erro:
Código: [Selecionar]
$ a="foo bar"
$ if [ $a = 0 ]; then echo sim; else echo não; fi
bash: [: too many arguments
não
O que é preciso compreender é que as aspas não servem como delimitadores de cadeias (nem fazem parte da sintaxe do if), mas para privar alguns caracteres, incluindo o espaço, das funções especiais.

Offline irtigor

  • Equipe Ubuntu
  • Usuário Ubuntu
  • *****
  • Mensagens: 4.344
  • Delete, delete, delete!
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #7 Online: 25 de Fevereiro de 2015, 19:46 »
O que estou dizendo é que levando em conta o contexto, a sua resposta no melhor dos casos é incompleta, não que aquilo não acontece. Não tem motivo nenhum pra ficar na defensiva.

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Dúvidas sobre o if (bash)
« Resposta #8 Online: 28 de Fevereiro de 2015, 11:30 »
Acho que eu entendi (tive que ler algumas vezes rs). Vamos lá:

Se eu declaro:

a="-n foo bla 0 8"

e coloco $a dentro da condição do if, o cifrão meio que come as aspas e transforma aquilo numa cadeia de comandos:

$a será igual a -n foo bla 0 8

porém se eu coloco "$a" ele verá essa cadeia de comandos como uma string, ou seja:
"$a" será igual a "-n foo bla 0 8"


É isso mesmo ???
Gentoo — Controle total sobre o sistema.

Offline irtigor

  • Equipe Ubuntu
  • Usuário Ubuntu
  • *****
  • Mensagens: 4.344
  • Delete, delete, delete!
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #9 Online: 28 de Fevereiro de 2015, 12:54 »
Isso foge um pouco da pergunta original, mas mostra porque uma das formas deve ser evitada. As aspas curvas e a contrabarra influenciam o jeito como a sua entrada é tratada, por isso há casos em que deve-se preferir um método especifico. Ex

Código: [Selecionar]
#!/usr/bin/bash -x

z="xx yy kk"
echo $z
echo "$z"

Você não armazena "xx yy kk" na variável z, a sua entrada é xx{espaço}yy{espaço}kk, e as aspas ao redor indicam que essa cadeia não deve ser separada em palavras por espaços. O mesmo acontece no echo "$z", essas aspas não impedem a expansão de parâmetros, então o bash substitui $z pelo seu conteúdo que é xx{espaço}yy{espaço}kk, mas elas não vão deixar a separação da cadeia em palavras com base no espaço.

Existem outras consequências: http://wiki.bash-hackers.org/syntax/quoting

Offline irtigor

  • Equipe Ubuntu
  • Usuário Ubuntu
  • *****
  • Mensagens: 4.344
  • Delete, delete, delete!
    • Ver perfil
Re: Dúvidas sobre o if (bash)
« Resposta #10 Online: 28 de Fevereiro de 2015, 19:19 »
Pra expandir em um ponto que toquei de leve, e aparentemente passou batido, no bash você até pode declarar uma variável com um tipo, mas o comum é usá-lo sem tipo (com tudo como strings, e com inferência/definição implícita em alguns casos). Isso faz sentido porque o shell é usado como uma linguagem de cola, você normalmente passa argumentos pra programas externos, e como a coisa é representada não faz parte do seu domínio.

http://mywiki.wooledge.org/BashGuide/Parameters#Variable_Types

Offline rudregues

  • Usuário Ubuntu
  • *
  • Mensagens: 388
  • Fight!
    • Ver perfil
    • Dieta Paleo
Re: Dúvidas sobre o if (bash)
« Resposta #11 Online: 01 de MAR?O de 2015, 16:02 »
muito interessante irtigor, problema resolvido!
(aprendi até coisas que nem imaginava rs)
Gentoo — Controle total sobre o sistema.