¿Qué hace que la utilidad de intérprete de bash interprete de manera diferente las comillas dobles estándar e inteligentes, presentes en un script de shell, creado en TextEdit?

3

Mientras aprendía los scripts de bash en una Guía para principiantes , intenté escribir algunos líneas de código en el archivo .sh , creadas en TextEdit en macOS Yosemite y ejecutándolas con el comando bash \path\to\script\file\example_script.sh en bash Terminal.

Línea de código que probé por primera vez:

echo “The path to my home directory is: $HOME”

Salida estándar (stdout) en la terminal:

“The path to my home directory is: ??

en lugar de obtener:

The path to my home directory is: /Users/Ri$hi

Luego, conocí el curioso caso de "smart quotes" de a stackexchange , y jugó con algunos combos divertidos, como a continuación:

Línea de código que probé más tarde:

Escenario 1:

echo “The path to my home directory is: $HOME (foo) bar”

stdout:

-bash: syntax error near unexpected token '('

Escenario 2:

echo "The path to my home directory is: $HOME (foo) bar"

stdout:

The path to my home directory is: /Users/Ri$hi (foo) bar

Escenario 3:

echo “The path to my home directory is: $HOME” “(foo)” “bar”

stdout:

-bash: syntax error near unexpected token '('

Escenario 4:

echo "The path to my home directory is: $HOME" “(foo)” “bar”

stdout:

-bash: syntax error near unexpected token '('

Escenario 5:

echo “The path to my home directory is: $HOME” "(foo)" “bar”

stdout:

“The path to my home directory is: ?? (foo) “bar”

Entonces, pensé por qué no descubrir el motivo de forma interactiva en este foro.

NOTA: el terminal siempre muestra la comilla doble estándar " cuando se presiona Shift + ", pero permite mostrar las comillas dobles inteligentes “ ” a través de + C , + V .

    
pregunta Rishi Khanna 30.08.2017 - 20:35

1 respuesta

9

Hay dos cosas que suceden aquí: en primer lugar, bash reconoce la comilla simple ASCII, " (código de carácter 0x22) como una comilla doble; no reconoce el elegante unicode izquierdo, doble comilla, (unicode U + 201C, UTF-8 que codifica 0xe2809c) y el correspondiente derecho doble, (unicode U + 201D, UTF-8 que codifica 0xe2809d) como cualquier otra cosa que no sean secuencias aleatorias de bytes (o tal vez como caracteres aleatorios, si se usa una configuración regional UTF-8). Esto es lo fundamental a tener en cuenta: en lo que respecta a bash, y no son realmente comillas , son cosas que parecen ser comillas cuando están impreso.

La segunda complicación es que las comillas dobles de Unicode son caracteres multibyte, por lo tanto, si bash no está en una configuración regional UTF-8, puede tratar algunos de los bytes de manera diferente que otros (!)

Para ver el efecto de lo primero, intente reemplazar cada aparición de una comilla doble con la cadena WIBBLE , otra secuencia arbitraria que no tiene un significado especial para el shell:

$ echo "The path to my home directory is: $HOME bar"
The path to my home directory is: /Users/gordon bar
$ echo “The path to my home directory is: $HOME bar”
“The path to my home directory is: /Users/gordon bar”
$ echo WIBBLEThe path to my home directory is: $HOME barWIBBLE
WIBBLEThe path to my home directory is: /Users/gordon barWIBBLE

En el primer comando (con comillas dobles ASCII), bash analiza y elimina las comillas antes de que los argumentos se pasen al comando echo y, por lo tanto, no se impriman. En el segundo y el tercero (con comillas dobles de lujo y WIBBLE en lugar de comillas simples), solo se tratan como parte de las cadenas que se pasan a echo , por lo que echo las imprime como parte de su salida.

$ echo "The path to my home directory is: $HOME (foo) bar"
The path to my home directory is: /Users/gordon (foo) bar
$ echo “The path to my home directory is: $HOME (foo) bar”
-bash: syntax error near unexpected token '('
$ echo WIBBLEThe path to my home directory is: $HOME (foo) barWIBBLE
-bash: syntax error near unexpected token '('

En el segundo y tercer comando (con comillas dobles de lujo y WIBBLE), bash ve paréntesis en una parte del comando que no está entre comillas (recuerde: en lo que respecta a bash, las comillas de fantasía son en realidad no comillas ), en un lugar donde no están permitidos por la sintaxis de shell, y por lo tanto se quejan.

$ echo “The path to my home directory is: $HOME”
“The path to my home directory is: ??
$ echo WIBBLEThe path to my home directory is: $HOMEWIBBLE
WIBBLEThe path to my home directory is:

Aquí, algo más extraño está sucediendo. En el segundo comando, busca una variable llamada HOMEWIBBLE , no la encuentra, por lo que la reemplaza con un espacio en blanco. En el caso del primero, con las comillas dobles sofisticadas, me parece que está tratando cada byte de la codificación UTF-8 de como un carácter separado, tratando al primero como parte del nombre de la variable (nuevamente causando que no se encuentre la variable), y luego simplemente pasando el segundo y tercer byte, dando un carácter UTF-8 no válido, que se imprime como ?? . Usar un volcado hexadecimal para tener una mejor idea de lo que está sucediendo da esto:

$ echo “$HOME”
“??
$ echo “$HOME” | xxd -g1
00000000: e2 80 9c 80 9d 0a                                ......

Tenga en cuenta que el primer pasa bien, y aparece en el volcado hexadecimal como e2 80 9c (el doble codificado en UTF-8 esperado), pero después de eso solo es 80 9d - el primero e2 de la segunda cita de lujo se comió de alguna manera! (Por cierto, el 0a al final es un salto de línea, que marca el final de la salida). Para ver qué sucede, permítame definir una variable de shell como HOME + el primer byte de la codificación de , y mira lo que pasa:

$ eval $'HOME\xe2=foo'
$ echo “$HOME”
“foo??
$ echo “$HOME” | xxd -g1
00000000: e2 80 9c 66 6f 6f 80 9d 0a                       ...foo...

... Así que está sucediendo: trata el primer byte de la codificación de la comilla doble como parte del nombre de la variable, lo sustituye (si está definido) y luego pasa a través del segundo y tercer byte huérfanos, dejando UTF-8 inválido. No estoy seguro de si se trata de un error de bash, la rareza de su análisis, o qué.

De todos modos, los detalles son un tanto desordenados, pero la información para llevar debe ser clara: no uses citas extravagantes en tus scripts de shell; no funcionarán bien Y lo mismo se aplica a las comillas simples y otras marcas de puntuación de Unicode.

    
respondido por el Gordon Davisson 30.08.2017 - 21:47

Lea otras preguntas en las etiquetas