Paréntesis en condición if: ¿por qué obtengo errores de sintaxis sin espacios en blanco?

17

Estoy usando la secuencia de comandos a continuación para retroceder dos días cuando la secuencia de comandos se ejecuta al comenzar dos días del año y también verificar el primer y segundo día de cada mes y retroceder dos días.

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

Pero lo malo es que recibo el siguiente mensaje de error

Etime_script.sh: line 19: [06=01]: command not found
Etime_script.sh: line 24: [06=01]: command not found
Kumar1
fuente
1
Las respuestas dadas son correctas; necesitas espacio en blanco después [. Además, mire la elifdeclaración; Te ayudará a limpiar las cosas. Además, los puntos y comas después de las declaraciones if no son necesarios, pero tampoco son incorrectos, simplemente extraños.
Shawn J. Goff
@ ShawnJ.Goff Son necesarios si concatena la siguiente línea ( if [ ... ]; then), así que no es tan inusual.
Ricitos de Oro
@goldilocks, sí, ese es mi estilo preferido. La razón por la que es inusual es porque él no está haciendo eso.
Shawn J. Goff

Respuestas:

27

[no es un metacarácter ni un operador de control (ni siquiera una palabra reservada; lo mismo para ]), por lo tanto, necesita espacios en blanco a su alrededor. De lo contrario el shell "ve" el comando [01=01]en lugar del comando [con los parámetros independientes 01, =, 01, y ]. Cada operador y operando debe ser un argumento separado del [comando, por lo que también es necesario un espacio en blanco alrededor de los operadores.

if [ "$month" = "01" ]

[$month="01"]es un patrón comodín que coincide con cualquiera de los caracteres en $montho "01. Si no coincide con nada, se deja solo.

Si hay un punto y coma después del corchete de cierre, no necesita un espacio antes, porque el punto y coma siempre forma parte de un token separado.

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

Lo mismo ocurre con la sintaxis de doble parche de bash (y ksh y zsh).

Más de una condición

Hay dos formas de combinar condiciones:

  1. dentro [

  2. con [comandos separados combinados con &&o||

Agrupar entre paréntesis es probablemente más fácil dentro [.

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

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

El primero debe evitarse ya que no es confiable (pruebe, por ejemplo, con month='!'). Los problemas con contenido variable extraño pueden evitarse utilizando primero la cadena segura (si hay una); o usando [[/ en ]]lugar de [/ ]:

if [ "01" = "$month" -a "01" = "$day" ]
Hauke ​​Laging
fuente
Cómo podemos hacer coincidir las dos condiciones en if, como el valor del mes == valor del día if [$ month = "01"] && [$ day = "01"]; estoy esperando 01 && 01 verdadero, luego imprima las siguientes condiciones o pase a la declaración else
Kumar1
@AshokSanganahalli He extendido mi respuesta.
Hauke ​​Laging
1
[cuando -a/ -ono se utilizan siempre es confiable con shells compatibles con POSIX. No hay ninguna ventaja en usar -a/-omás &&/||. Definitivamente desalentaría su uso. Tenga en cuenta que [[no es POSIX.
Stéphane Chazelas
4

Otra forma de escribirlo:

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
fuente
1
+1 para casedeclaración. Si tiene más de uno elif, probablemente debería estar usando case.
HalosGhost
-1

Entonces, esta es tu respuesta:

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

Por lo tanto, debe poner "espacio" entre corchetes y variable / valor.

Neven
fuente
no, supongo, porque como le pedí al script que retrocediera dos días cuando el script se ejecuta al comenzar dos días del año y también verifique el primer y segundo día de cada mes y retroceder dos días significa aquí si [$ mes = "01"] && [$ day = "01"] suponemos que coincide con el mes "01" y el primer día "01" verdadero, pasar a la condición de entonces o pasar a otra condición
Kumar1
1
@AshokSanganahalli: No sé cómo se relaciona esto, pero su condición IF no funciona porque no tiene "espacio en blanco" entre corchetes y valor
Neven
@AshokSanganahalli Por lo general, no es una buena idea que las personas en su nivel de habilidad discutan las correcciones de las personas con una comprensión obviamente mejor sin al menos intentarlo. Si sus conjeturas fueran correctas, entonces no tendría que preguntar aquí, ¿verdad?
Hauke ​​Laging
44
-1 para variables no citadas y uso de en ==lugar de estándar =.
Stéphane Chazelas
2
La pregunta no está etiquetada bash. El operador de comparación de igualdad en el comando aka estándar[test es =. [si para las pruebas, no realiza ninguna tarea, por lo que no hay necesidad de desambiguar. Algunas [implementaciones admiten ==como una extensión sobre el estándar, pero no todas. El shell Bourne, ash's, posh' [s o el /bin/[de algunos sistemas, por ejemplo, no. ==fue agregado por ksh, supongo, por coherencia con el mismo operador en su nueva (( ... ))construcción (que tiene ambos = y ==, pero no es estándar)
Stéphane Chazelas