¿Cuáles son algunos casos en los que el número de espacios sí importa en los scripts de bash (u otro shell)

14

Me han dicho que los espacios son importantes en bashotros scripts de shell y que no debería cambiar la existencia de espacios a menos que sepa lo que estoy haciendo. Por "cambiar la existencia" me refiero a insertar un espacio entre dos caracteres no espaciales o eliminar un espacio entre dos caracteres no espaciales, por ejemplo, cambiar var="$val"a var ="$val"o viceversa. Quiero preguntar

¿Hay algún caso en el que el uso de un solo espacio o el uso de múltiples espacios consecutivos en un script de shell marque la diferencia? .

(Por supuesto, la inserción / eliminación de un espacio entre comillas hace la diferencia, como cambiar a partir echo "a b"de echo "a b", o viceversa. Busco ejemplos distintos a este ejemplo trivial.)

Me he encontrado con esta pregunta, pero se trata de agregar y eliminar espacios entre dos caracteres que no son espacios, para lo cual conozco muchos ejemplos que marcarían la diferencia.

Cualquier ayuda sería apreciada. Incluya más variedades de conchas si es posible.

Weijun Zhou
fuente

Respuestas:

19

Fuera de las comillas, el shell utiliza espacios en blanco (espacios, tabulaciones, nueva línea, retorno de carro, etc.) como un separador de palabra / token. Eso significa:

  • Las cosas que no están separadas por espacios en blanco se consideran una "palabra".
  • Las cosas separadas por uno o más espacios en blanco se consideran dos (o más) palabras.

El número real de caracteres de espacio en blanco entre cada "cosa" no importa, siempre que haya al menos uno.

cas
fuente
Gracias. No puedo encontrar ningún contraejemplo yo mismo. Solo quiero asegurarme.
Weijun Zhou
2
Bash también considera que los feeds de formularios y las pestañas verticales son espacios en blanco.
fpmurphy
cierto. Originalmente escribí '... líneas nuevas, etc.' y luego lo cambié para agregar explícitamente retornos de carro. accidentalmente se cayó el 'etc'.
cas
¿Qué sucede si el número de espacios es tan grande que el programa no puede caber en la memoria?
Worse_Username
77
@Worse_Username El espacio en blanco no tiene que caber en la memoria. Acabo de crear un script de 48 GB en una máquina con 8 GB de RAM y 20 GB de intercambio. Funcionó muy bien. Le tomó 3 minutos procesar todo ese espacio en blanco, pero al final ejecutó con éxito un echocomando con tanto espacio en blanco entre el comando y el argumento.
kasperd
23

Probablemente esto sea trampa, pero esto:

rm foo\ bar         # "delete the file named 'foo bar'"

es diferente de esto:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

a pesar de que los espacios no están entre comillas. ;-)

Más confuso, esto:

rm \
    foo          # "delete the file named 'foo'"

es diferente de esto:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

a pesar de que se ven idénticos!

ruakh
fuente
A pesar de que los espacios no están entre comillas, la barra diagonal inversa es funcionalmente similar a la forma de las citas y lo pondría en la misma categoría que el "ejemplo trivial" de la pregunta. (Sin embargo, es interesante.)
David Z
12

Si no hablamos sobre el carácter de espacio ( U+0020), pero ningún espacio en blanco ( U+0020, \n, \t, etc.), a continuación, un caso particular, vienen a la mente: los documentos internos.

Este código (usando espacios):

cat <<- 'EOF'
<space><space>foo
EOF

Imprimirá:

  foo

Pero este código (usando pestañas):

cat <<- 'EOF'
<tab><tab>foo
EOF

Imprimirá:

foo

Eso es porque ( como afirma POSIX ):

Si el operador de redirección es <<-, todos los caracteres <tab> iniciales se eliminarán de las líneas de entrada y de la línea que contiene el delimitador final.

nxnev
fuente
1
Eso es interesante. Pensé en los documentos aquí, pero no conocía al <<-operador. Muchas gracias.
Weijun Zhou
aquí los documentos son una forma de texto citado, no un código shell. la división de palabras de shell no se aplica.
cas
2

También tiene un efecto al escribir declaraciones de asignación. Como si dijera FOO=xyzque creará una variable de entorno llamada FOOcon valor xyz, pero si separo los iguales con un espacio, pensará que estoy invocando un programa llamado FOOcon el argumento =xyz. Entonces sí importa cuando se trata de cierta sintaxis.

HSchmale
fuente
Por FOO=xyzlo general , crea una variable de shell interna pero no una variable de entorno. Necesita set -ao export FOO=xyzpara eso (es decir, hacer que forme parte del entorno de subprocesos que no son subshell).
Hauke ​​Laging