Pregunta ¿Por qué a veces se necesita espacio en blanco alrededor de metacaracteres?


Hace unos meses me tatué tenedor bomba en mi brazo, y salté los espacios en blanco, porque creo que se ve mejor sin ellos. Pero para mi consternación, a veces (no siempre) cuando lo ejecuto en un shell no se inicia una bomba de horquilla, sino que simplemente da un error de sintaxis.

bash: syntax error near unexpected token `{:'

Ayer sucedió cuando traté de ejecutarlo en un amigo Intento shell, y luego agregué el espacio en blanco y de repente funcionó, :(){ :|:& };: en lugar de :(){:|:&};:

¿El espacio en blanco importa? ¿He tatuado un error de sintaxis en mi brazo?

Parece que siempre funciona en zsh, pero no en Bash.

Una pregunta relacionada no explica nada sobre los espacios en blanco, que realmente es mi pregunta; ¿Por qué es necesario el espacio en blanco para que Bash pueda analizarlo correctamente?


533
2018-01-17 13:03


origen


Respuestas:


Hay una lista de caracteres que separan tokens en BASH. Estos personajes son llamados metacaracteres y estan |, &, ;, (, ), <, >, espacio y lengüeta. Por otro lado, llaves ({ y }) son solo personajes ordinarios que forman palabras.

Omitir el segundo espacio antes } va a hacer, ya que & es un metacarácter Por lo tanto, tu tatuaje debe tener al menos un carácter de espacio.

:(){ :|:&};:

262
2018-01-17 13:20



Solo tatúa un

#!/bin/zsh

shebang por encima y estarás bien.


76
2018-01-29 12:26



Las llaves son más como palabras clave extrañas que símbolos especiales, y necesitan espacios. Esto es diferente a paréntesis, por ejemplo. Comparar:

(ls)

que funciona, y:

{ls}

que busca un comando llamado {ls}. Para trabajar, tiene que ser:

{ ls; }

El punto y coma detiene la llave de cierre que se toma como un parámetro para ls.

Todo lo que tiene que hacer es decirle a la gente que está usando una fuente proporcional con un carácter de espacio bastante estrecho.


49
2018-01-17 13:09



Aunque no es fácilmente visible en la fuente del tatuaje, en realidad hay una Marca de Orden de Byte (BOM) entre el paréntesis y el colon (es posible que haya estado lo suficientemente intoxicado cuando recibió el tatuaje que no lo notó, pero realmente está allí) . Esto deja tres posibilidades obvias:

  1. Error al escribir la lista de materiales cuando transcribiste el código. El resultado es una aplicación obvia de GIGO. El shell simplemente no reconoce una lista de materiales que no está presente en su transcripción fallida.
  2. Tu caparazón es muy viejo. No reconoce caracteres Unicode, por lo que la lista de materiales (y probablemente todos los demás caracteres Unicode) se ignora por completo, aunque una BOM en cualquier lugar, pero el comienzo de un archivo se debe tratar como un espacio de ancho cero sin interrupción .
  3. Tu caparazón es demasiado nuevo. El uso de una lista de materiales como ZWNBS está en desuso, y los autores han implementado una versión futura de Unicode en la que este uso ya no está permitido.

40
2018-01-22 03:58



y luego agregué el espacio en blanco y de repente funcionó ...

Es por la forma en que el shell analiza. Necesita un espacio después de que comienza la definición de la función, es decir, después de la {.

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}

son validos. Por otra parte,

foo() {echo hey&}

no es


Realmente necesitas un tatuaje como este:

enter image description here


Desde el fuente:

  /* We ignore an open brace surrounded by whitespace, and also
     an open brace followed immediately by a close brace preceded
     by whitespace.  */

Omitir un espacio después de la { causa el {echo para ser interpretado como un solo token.


Una forma equivalente de

:(){ :|:& };:

sería

:(){
:|:& };:

Tenga en cuenta que no hay espacio después { en la versión alternativa, pero un salto de línea hace que el shell reconozca { como una ficha


39
2018-01-17 13:12