¿Por qué a veces se necesitan espacios en blanco alrededor de metacaracteres?


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

bash: syntax error near unexpected token `{:'

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

Hace el espacio en blanco materia; 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é se necesita el espacio en blanco para que Bash pueda analizarlo correctamente?

Author: codeforester, 2014-01-17

5 answers

Hay una lista de caracteres que separan los tokens en BASH. Estos caracteres se denominan metacaracteres y ellos son |, &, ;, (, ), <, >, el espacio y ficha. Por otro lado, las llaves ({ y }) son solo caracteres ordinarios que componen las palabras.

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

:(){ :|:&};:
 262
Author: Dmitri Chubarov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-09 15:16:07

Solo tatuaje a

#!/bin/zsh

Shebang encima de él y estarás bien.

 76
Author: SzG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-08 14:10:51

Las llaves se parecen más a palabras clave impares que a símbolos especiales, y necesitan espacios. Esto es diferente a los paréntesis, por ejemplo. Comparar:

(ls)

Que funciona, y:

{ls}

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

{ ls; }

El punto y coma impide que la llave de cierre se tome como parámetro de ls.

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

 49
Author: Peter Westlake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-17 13:18:11

Aunque no es fácilmente visible en la fuente tatoo, en realidad hay una Marca de Orden de bytes (BOM) entre el corsé y el colon (puede que hayas estado lo suficientemente intoxicado cuando te hiciste el tatuaje que no lo notaste, pero realmente está ahí). Esto deja tres posibilidades obvias:

  1. No ha podido escribir la lista de materiales cuando transcribió 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 fallo transcripción.
  2. Tu caparazón es demasiado viejo. No reconoce caracteres Unicode, por lo que la lista de materiales (y probablemente todos los demás caracteres Unicode) está siendo ignorada por completo, a pesar de que una lista de materiales en cualquier lugar, excepto el comienzo de un archivo, se supone que debe tratarse como un espacio de ancho cero y sin interrupciones.
  3. Tu shell 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
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-22 04:43:23

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

Es debido a cómo el shell analiza. Necesita un espacio después de que comience la definición de la función, es decir, después de {.

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

Son válidos. Por otra parte,

foo() {echo hey&}

No lo es.


Realmente necesitas un tatuaje como este:

introduzca la descripción de la imagen aquí


De la 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 { hace que {echo sea interpretado como un único token.


Una forma equivalente de

:(){ :|:& };:

Sería

:(){
:|:& };:

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

 39
Author: devnull,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-21 20:34:06