Parênteses na condição if: por que estou recebendo erros de sintaxe sem espaço em branco?

17

Estou usando o script abaixo para retornar dois dias quando o script é executado no início de dois dias do ano e também verificar o primeiro e o segundo dia de cada mês e retornar dois dias atrás.

if [$month="01"] && [$day="01"];
then
    date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
if [$month="01"] && [$day="02"];
then
         date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
   if [ $day = "01" ];
then
    date="$last_month/$yes_day/$year"
            fulldate="$year$last_month$yes_day"
else
        if [ $day = "02" ];
then
    date="$last_month/$yes_day/$year"
        fulldate="$year$last_month$yes_day"
else
    date="$month/$yes_day/$year"
        fulldate="$year$month$yes_day"
                fi
               fi
              fi
fi

Mas meu mal estou recebendo a mensagem de erro abaixo

Etime_script.sh: line 19: [06=01]: command not found
Etime_script.sh: line 24: [06=01]: command not found
Kumar1
fonte
1
As respostas dadas estão corretas; você precisa de espaço em branco depois [. Além disso, examine a elifdeclaração; isso ajudará você a limpar as coisas. Além disso, os pontos e vírgulas após as instruções if não são necessários, mas também não são incorretos, apenas estranhos.
amigos estão
@ ShawnJ.Goff Eles são necessários se você concatenar a próxima linha ( if [ ... ]; then), então isso não é incomum.
precisa
@ goldilocks, sim, esse é o meu estilo preferido. A razão pela qual é incomum é porque ele não está fazendo isso.
Shawn J. Goff

Respostas:

27

[não é um metacaractere nem um operador de controle (nem mesmo uma palavra reservada; é a mesma para ]), portanto, precisa de espaço em branco ao seu redor. Caso contrário, o shell "vê" o comando [01=01]em vez do comando [com os parâmetros separados 01, =, 01, e ]. Cada operador e operando precisa ser um argumento separado para o [comando, portanto, também é necessário espaço em branco ao redor dos operadores.

if [ "$month" = "01" ]

[$month="01"]é um padrão curinga que corresponde a qualquer um dos caracteres em $monthou "01. Se não corresponder a nada, será deixado sozinho.

Se houver um ponto e vírgula após o colchete de fechamento, você não precisará de um espaço antes dele, porque o ponto e vírgula sempre faz parte de um token separado.

if [ "$month" = "01" ]; then

O mesmo vale para a sintaxe de colchete duplo do bash (e ksh e zsh).

Mais de uma condição

Existem duas maneiras de combinar condições:

  1. dentro [

  2. com [comandos separados combinados com &&ou||

O agrupamento com parênteses é provavelmente mais fácil por dentro [.

if [ "$month" = "01" -a "$day" = "01" ] # -a for and, -o for or

if [ "$month" = "01" ] && [ "$day" = "01" ]

O primeiro deve ser evitado, pois não é confiável (tente, por exemplo, com month='!'). Problemas com conteúdo variável estranho podem ser evitados usando a string segura (se houver) primeiro; ou usando [[/ em ]]vez de [/ ]:

if [ "01" = "$month" -a "01" = "$day" ]
Hauke ​​Laging
fonte
Como podemos combinar as duas condições em if, como valor do mês == valor do dia se [$ month = "01"] && [$ day = "01"]; estou esperando 01 && 01 verdade, então imprimir abaixo das condições ou mudar para outra declaração
Kumar1
@AshokSanganahalli Estendi minha resposta.
Hauke ​​Laging
1
[quando -a/-o não é usado é sempre confiável com os shells compatíveis com POSIX. Não há nenhuma vantagem em usar -a/-omais &&/||. Eu definitivamente desencorajaria seu uso. Observe que [[não é POSIX.
Stéphane Chazelas
4

Outra maneira de escrever:

case $month:$day in
  (01:0[12])
    date="$last_month/$yes_day/$last_year"
    fulldate="$last_month/$yes_day/$last_year"
    ;;
  (*:0[12])
    date="$last_month/$yes_day/$year"
    fulldate="$year$last_month$yes_day"
    ;;
  (*)
    date="$month/$yes_day/$year"
    fulldate="$year$month$yes_day"
esac
Stéphane Chazelas
fonte
1
+1 para a casedeclaração. Se você tiver mais de um elif, provavelmente deveria estar usando case.
precisa saber é o seguinte
-1

Então, esta é sua resposta:

if [ $var1 == $var2 ];
 then
    echo "bla bla"
fi

Portanto, você deve colocar "espaço" entre colchetes e variável / valor.

Neven
fonte
no i GUESS, porque, como pedi ao script para voltar dois dias quando o script é executado no início de dois dias do ano e também verificar o primeiro e o segundo dia de cada mês e voltar dois dias significa aqui se [$ month = "01"] && [$ day = "01"] supomos para corresponder mês "01" e no primeiro dia "01" verdade, movimento para, em seguida, ou mudança para a condição else
Kumar1
1
@AshokSanganahalli: Eu não sei como isso é relacionado, mas sua condição IF não está funcionando porque você não tem "espaço em branco" entre colchetes e valor
Neven
@AshokSanganahalli Normalmente, não é uma boa ideia para pessoas do seu nível de habilidade contestar correções de pessoas com uma compreensão obviamente melhor sem pelo menos tentar a dica. Se seus palpites estivessem certos, você não precisaria perguntar aqui, precisaria?
Hauke ​​Laging
4
-1 para variáveis ​​não citadas e uso de em ==vez de padrão =.
Stéphane Chazelas
2
A pergunta não está marcada como bash. O operador de comparação de igualdade no comando aka padrão[test é =. [se for para testes, ele não realiza nenhuma tarefa, portanto não há necessidade de desambiguar. Algumas [implementações suportam ==como uma extensão acima do padrão, mas não todas. Os shell Bourne, ash's, posh' [s ou o /bin/[de alguns sistemas, por exemplo, não. ==adicionou-se por ksh, que supor, por consistência com o mesmo operador na sua nova (( ... ))construo (que tem ambos = e ==, mas nenhum padrão)
Stéphane Chazelas