Expansión de cadenas entre comillas y sin comillas


11
  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

Entiendo por qué 1 difiere de 2. Pero ¿por qué 3 da una salida diferente de 2? Por favor explique la salida también. ¿Cómo funcionan las citas en las nuevas líneas?



Respuestas:


19

Una variable sin comillas (como en $var) o una sustitución de comando (como en $(cmd)o `cmd`) es el operador split + glob en shells tipo Bourne.

Es decir, su contenido se divide de acuerdo con el valor actual de la $IFSvariable especial (que por defecto contiene el espacio, la pestaña y los caracteres de nueva línea)

Y luego cada palabra resultante de esa división está sujeta a la generación de nombre de archivo (también conocido como expansión global o de nombre de archivo ), es decir, se consideran patrones y se expanden a la lista de archivos que coinciden con ese patrón.

Entonces for i in $(xrandr), el $(xrandr), porque no está entre comillas, se divide en secuencias de caracteres de espacio, tabulación y nueva línea. Y cada palabra resultante de esa división se verifica para buscar nombres de archivo coincidentes (o se deja como está si no coinciden con ningún archivo), y se forrepite sobre todos ellos.

En for i in "$(xrandr)", no estamos utilizando el operador split + glob como se cita la sustitución del comando , por lo que hay un pase en el bucle en un valor: la salida de xrandr(sin los caracteres de nueva línea que ordenan las tiras de sustitución del comando ).

Sin embargo echo $i, en , $ino se vuelve a citar, por lo que nuevamente el contenido de $ise divide y está sujeto a la generación de nombre de archivo y se pasan como argumentos separados al echocomando (y echogenera sus argumentos separados por espacios).

Entonces, la lección aprendida:

  • si no desea la división de palabras o la generación de nombre de archivo , siempre cite expansiones variables y sustituciones de comandos
  • si desea la división de palabras o la generación de nombre de archivo , déjelas sin comillas pero configúrelas en $IFSconsecuencia y / o habilite o deshabilite la generación de nombre de archivo si es necesario ( set -f, set +f).

Por lo general, en su ejemplo anterior, si desea recorrer la lista de palabras separadas en blanco en la salida de xrandr, necesitaría:

  • dejar $IFSen su valor predeterminado (o desarmarlo) para dividir en espacios en blanco
  • Uso set -fde generar nombres de archivos deshabilitar menos que esté seguro de que xrandrno emite ninguna *o ?o [caracteres (que se utilizan caracteres comodín en patrones de generación de nombre de archivo)

Y luego solo use el operador split + glob (solo deje la sustitución del comando o la expansión variable sin comillas) en la inparte del forbucle:

set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done

Si desea recorrer las líneas (no vacías) de la xrandrsalida, deberá establecer $IFSel carácter de nueva línea:

IFS='
'

4

Una nueva línea citada es una nueva línea. Entonces echo "$1"da un argumento de línea de comando único para echo, que luego imprime las nuevas líneas directamente.

Una nueva línea sin comillas es un espacio en blanco. Por lo tanto, echo $1ofrece muchos argumentos de línea de comandos para echo, que los imprime uno tras otro separados por espacios.


Una nueva línea sin comillas es que el espacio en blanco es demasiado corto para ser realmente útil como explicación del comportamiento aquí en la OMI.
Stéphane Chazelas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.