Tengo algunos scripts de shell de Unix donde necesito verificar que ciertas variables de entorno estén configuradas antes de comenzar a hacer cosas, así que hago este tipo de cosas:
if [ -z "$STATE" ]; then
echo "Need to set STATE"
exit 1
fi
if [ -z "$DEST" ]; then
echo "Need to set DEST"
exit 1
fi
que es mucho escribir ¿Existe una expresión más elegante para verificar que se establece un conjunto de variables de entorno?
EDITAR: Debo mencionar que estas variables no tienen un valor predeterminado significativo: el script debe generar un error si alguno no está configurado.
Respuestas:
Expansión de parámetros
La respuesta obvia es usar una de las formas especiales de expansión de parámetros:
O, mejor (vea la sección 'Posición de comillas dobles' a continuación):
La primera variante (usando solo
?
) requiere que se establezca STATE, pero STATE = "" (una cadena vacía) está bien, no exactamente lo que desea, sino la notación alternativa y anterior.La segunda variante (usando
:?
) requiere que DEST esté configurado y no esté vacío.Si no proporciona ningún mensaje, el shell proporciona un mensaje predeterminado.
La
${var?}
construcción es portátil de nuevo a la Versión 7 UNIX y Bourne Shell (1978 o más o menos). La${var:?}
construcción es un poco más reciente: creo que estaba en System III UNIX alrededor de 1981, pero puede haber estado en PWB UNIX antes de eso. Por lo tanto, está en Korn Shell y en los shells POSIX, incluido específicamente Bash.Por lo general, se documenta en la página de comando man de la shell en una sección llamada Expansión de parámetros . Por ejemplo, el
bash
manual dice:El comando de colon
Probablemente debería agregar que el comando de dos puntos simplemente tiene sus argumentos evaluados y luego tiene éxito. Es la notación de comentario de shell original (antes de '
#
' al final de la línea). Durante mucho tiempo, los scripts de shell Bourne tenían dos puntos como primer carácter. El C Shell leería un script y usaría el primer carácter para determinar si era para el C Shell (un#
"hash" o el shell Bourne (un:
"dos puntos"). Luego, el kernel entró en acción y agregó soporte para "#!/path/to/program
y el shell Bourne recibió#
comentarios", y la convención de colon quedó en el camino. Pero si te encuentras con un script que comienza con dos puntos, ahora sabrás por qué.Posición de comillas dobles
Blong preguntó en un comentario :
La esencia de la discusión es:
La respuesta corta es "haz lo que
shellcheck
sugieras":Para ilustrar por qué, estudie lo siguiente. Tenga en cuenta que el
:
comando no hace eco de sus argumentos (pero el shell evalúa los argumentos). Queremos ver los argumentos, por lo que el siguiente código se utilizaprintf "%s\n"
en lugar de:
.Observe cómo el valor en
$x
se expande primero*
y luego una lista de nombres de archivo cuando la expresión general no está entre comillas dobles. Esto es lo queshellcheck
se recomienda que se arregle. No he verificado que no se oponga al formulario donde la expresión está entre comillas dobles, pero es una suposición razonable que estaría bien.fuente
if [ "$variable" = "abc" ]; then : OK; else : variable is not set correctly; fi
.Prueba esto:
fuente
[ -z "$STATE" ] && { echo "Need to set STATE"; exit 1; }
vea esta publicación de blogSu pregunta depende del shell que esté utilizando.
Bourne Shell deja muy poco en lo que busca.
PERO...
Funciona, casi en todas partes.
Solo trata de mantenerte alejado de csh. Fue bueno para las campanas y silbatos que agregó, en comparación con el shell Bourne, pero ahora es realmente crujiente. Si no me cree, ¡solo intente separar STDERR en csh! (-:
Hay dos posibilidades aquí. El ejemplo anterior, a saber, usando:
Por primera vez, debe consultar $ MyVariable. Esto toma el env. var MyVariable y, si actualmente no está configurado, asigna el valor de SomeDefault a la variable para su uso posterior.
También tienes la posibilidad de:
que solo sustituye SomeDefault por la variable donde está utilizando esta construcción. No asigna el valor SomeDefault a la variable, y el valor de MyVariable seguirá siendo nulo después de que se encuentre esta declaración.
fuente
Seguramente el enfoque más simple es agregar el
-u
interruptor al shebang (la línea en la parte superior de su script), suponiendo que esté usandobash
:#!/bin/sh -u
Esto hará que la secuencia de comandos salga si hay alguna variable no ligada dentro.
fuente
Si
MyVariable
se establece y no es nulo, restablecerá el valor de la variable (= no sucede nada).De lo contrario,
MyVariable
se establece enSomeDefault
.Lo anterior intentará ejecutarse
${MyVariable}
, por lo que si solo desea establecer la variable, haga lo siguiente:fuente
En mi opinión, la verificación más simple y compatible para #! / Bin / sh es:
Una vez más, esto es para / bin / sh y es compatible también en sistemas Solaris antiguos.
fuente
/bin/sh
soporte para la${var:?}
notación, etc.unset MYVAR
yMYVAR=
.foo
está configurado,"$foo"
aún se expande a la cadena vacía.bash
4.2 introdujo el-v
operador que prueba si un nombre se establece en algún valor, incluso la cadena vacía.fuente
Siempre usé:
No mucho más conciso, me temo.
Bajo CSH tienes $? ESTADO.
fuente
STATE
está vacío o sin configurar, no solo sin configurar.Para las personas futuras como yo, quería dar un paso adelante y parametrizar el nombre de la variable, para poder recorrer una lista de nombres de variables de tamaño variable:
fuente
Podemos escribir una buena afirmación para verificar un montón de variables a la vez:
Invocación de muestra:
Salida:
Más afirmaciones de este tipo aquí: https://github.com/codeforester/base/blob/master/lib/assertions.sh
fuente
Esto también puede ser una forma:
http://unstableme.blogspot.com/2007/02/checks-whether-envvar-is-set-or-not.html
fuente
Ninguna de las soluciones anteriores funcionó para mis propósitos, en parte porque comprobé el entorno en busca de una lista abierta de variables que deben establecerse antes de comenzar un proceso largo. Terminé con esto:
fuente
En lugar de usar scripts de shell externos, tiendo a cargar funciones en mi shell de inicio de sesión. Utilizo algo como esto como una función auxiliar para verificar las variables de entorno en lugar de cualquier variable establecida:
fuente
is_this_an_env_variable P
devolverá el éxito porquePATH
existe.La
$?
sintaxis es bastante clara:fuente
$?
encuentra el estado de salida del comando anterior;$?BLAH
es la cadena que consiste en el estado de salida del comando anterior concatenado con 'BLAH'. Esto no prueba la variable$BLAH
en absoluto. (Hay un rumor de que podría hacer más o menos lo que se requierecsh
, pero es mejor dejar las conchas marinas en la orilla del mar).