bash - una - ¿Debo usar comillas en los nombres de ruta de entorno?
variables en bash (3)
Estoy en el proceso de limpiar todos mis archivos de configuración en un intento de hacerlos lo más legibles posible. He estado buscando una guía de estilo sobre el uso de comillas al exportar rutas en, por ejemplo, un archivo ~/.bashrc
:
export PATH="/users/me/path:$PATH"
vs
export PATH=/users/me/path:$PATH
La guía de estilo de shell de Google sugiere evitar citas para nombres de ruta. En contraste, muchos de los repositorios de archivos de puntos populares (como Zach Holman here ) usan comillas. ¿Hay situaciones en las que es una ventaja usar comillas en la ruta?
Utilicé estas respuestas arriba cuando establecí nombres de rutas de entorno en un archivo .env de ventana acoplable, y obtuve bits. Pongo esto aquí para cualquier otra persona que busque cómo definir las variables de entorno para la ventana acoplable.
Docker compose lee las variables de entorno de un archivo .env que existe en la misma carpeta que la ventana acoplable se ejecuta como se indica aquí https://docs.docker.com/compose/env-file.
Sin embargo, en lugar de envolver el valor entre comillas, el componente de Docker necesita la variable de entorno definida sin comillas, a menos que las comillas formen parte del valor. Una vez más, como se indica en la url anterior
No hay un manejo especial de comillas (es decir, serán parte del VAL, se le ha advertido)
Estaba intentando configurar NODE_PATH=./src
para que las rutas absolutas funcionen en una aplicación de reacción que está desplegando la NODE_PATH="./src"
acoplable, pero la había escrito como NODE_PATH="./src"
. Esta advertencia me sacó de 4 horas de conejo.
test 123
es un nombre de ruta válido en UNIX. Tratar
PATH=test 123
Volverá
123: command not found
O incluso
export PATH=test 123
que volverá
bash export: `123'': not a valid identifier
¿Responde tu pregunta?
Sinceramente, no seguiría esas guías de estilo de cuarta fiesta. Aunque me sorprende que incluso Google anuncie consejos tan equivocados.
Yo seguiría:
- http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html
- http://www.tldp.org/LDP/abs/html/
- https://www.gnu.org/software/bash/manual/bash.html
(para ser cuidadosamente extendido)
Punta del sombrero a gniourf_gniourf y @chepner por su ayuda.
tl; dr
Para estar seguro, doble cita: funcionará en todos los casos, en todas las carcasas tipo POSIX.
Si desea agregar una ruta basada en ~
, deje selectivamente ~/
unquoted para asegurarse de que ~
se expande; Ej .: export PATH=~/"bin:$PATH"
. Vea a continuación las reglas de expansión en asignaciones de variables.
Alternativamente, simplemente use $HOME
dentro de una cadena de comillas dobles:
export PATH="$HOME/bin:$PATH"
NOTA: Lo siguiente se aplica a bash
, ksh
y zsh
, pero NO a (en su mayoría) shells estrictamente compatibles con POSIX como dash
; por lo tanto, cuando apunta a /bin/sh
, DEBE citar el RHS de export
. [1]
- Las comillas dobles son opcionales , SOLAMENTE SI la parte literal de su RHS (el valor a asignar) no contiene espacios en blanco ni otros metacaracteres de shell.
- Si los valores de las variables a las que se hace referencia contienen espacios en blanco / metacaracteres o no, no importa, consulte a continuación.
- De nuevo: sí importa con
sh
, cuando se usa laexport
, así que siempre doble comillas allí.
- De nuevo: sí importa con
La razón por la que puede salir sin comillas dobles en este caso es que las declaraciones de asignación de variables en shells POSIX interpretan su RHS de manera diferente a los argumentos pasados a los comandos , como se describe en la sección 2.9.1 de la especificación POSIX:
Específicamente, aunque la división de palabras inicial se realiza, solo se aplica a la RHS sin expandir (en bruto) (por eso es necesario citar con espacios en blanco / metacaracteres en literales ), y no a sus resultados .
Esto solo se aplica a las declaraciones de cesión genuinas del formulario.
<name>=<value>
en todos los shells similares a POSIX , es decir, si no hay un nombre de comando antes del nombre de la variable; tenga en cuenta que eso incluye asignaciones ante un comando para definir variables de entorno ad hoc, por ejemplo,foo=$bar cmd ...
Las asignaciones en el contexto de otros comandos siempre deben estar entre comillas dobles , para estar seguros:
Con
sh
(en un shell (en su mayoría) estrictamente compatible con POSIX como undash
) una asignación conexport
se trata como un comando regular , y la partefoo=$bar
se trata como el primer argumento de laexport
incorporada y, por lo tanto, se trata como siempre (sujeto a la división de palabras del resultado , también).
(POSIX no especifica ningún otro comando que involucre asignación de variables (explícita);declare
,typeset
ylocal
son extensiones no estándar).bash
,ksh
,zsh
, en una desviación comprensible de POSIX, extiende la lógica de asignación paraexport foo=$bar
ytypeset/declare/local foo=$bar
también. En otras palabras: enbash
,ksh
,zsh
,export/typeset/declare/local
comandosexport/typeset/declare/local
se tratan como asignaciones , por lo que no es estrictamente necesario citar .- Quizás sorprendentemente, el
dash
, que también optó por implementar la función incorporadalocal
no es -POSIX [2] , NO le extiende la lógica de asignación; Sin embargo, es consistente con su comportamiento deexport
.
- Quizás sorprendentemente, el
Las asignaciones pasadas a
env
(por ejemplo,env foo=$bar cmd ...
) también están sujetas a expansión como un argumento de comando y, por lo tanto, necesitan comillas dobles, excepto enzsh
.- El hecho de que
env
actúe de forma diferente a laexport
enksh
ybash
en este sentido se debe al hecho de queenv
es una utilidad externa , mientras que laexport
es un shell incorporado .
(El comportamiento dezsh
difiere fundamentalmente del de los otros shells cuando se trata de referencias de variables sin comillas).
- El hecho de que
La expansión de Tilde (
~
) ocurre de la siguiente manera en declaraciones de asignación genuinas :- Además de que
~
necesita comillas , como es habitual, también se aplica solo:- Si todo el RHS es
~
; p.ej:-
foo=~ # same as: foo="$HOME"
-
- De lo contrario: solo si se cumplen las dos condiciones siguientes:
- Si
~
inicia la cadena o está precedido por un sin comillas:
- si
~
es seguido por un/
comillas . - p.ej,
foo=~/bin # same as foo="$HOME/bin"
foo=$foo:~/bin # same as foo="$foo:$HOME/bin"
- Si
- Si todo el RHS es
- Además de que
Ejemplo
Este ejemplo demuestra que, en bash
, ksh
y zsh
, puede salir sin comillas dobles, incluso cuando utiliza la export
, pero no lo recomiendo .
#!/usr/bin/env bash
# or ksh or zsh - but NOT /bin/sh!
# Create env. variable with whitespace and other shell metacharacters
export FOO="b:c &|<> d"
# Extend the value - the double quotes here are optional, but ONLY
# because the literal part, ''a:`, contains no whitespace or other shell metacharacters.
# To be safe, DO double-quote the RHS.
export FOO=a:$foo # OK - $FOO now contains ''a:b:c &|<> d''
[1] Como @gniourf_gniourf señala: el uso de export
para modificar el valor de PATH
es opcional, porque una vez que una variable se marca como exportada, puede usar una asignación regular ( PATH=...
) para cambiar su valor.
Dicho esto, aún puede optar por utilizar la export
, para que sea explícito que la variable que se está modificando se exporta.
[2] @gniourf_gniourf indica que una versión futura del estándar POSIX puede introducir el componente interno local
.