Expansión de parámetros
La respuesta obvia es usar una de las formas especiales de expansión de parámetros:
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
O, mejor (vea la sección 'Posición de comillas dobles' a continuación):
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
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:
${parameter:?word}
Mostrar error si es nulo o desarmado. Si el parámetro es nulo o no está establecido, la expansión de la palabra (o un mensaje a tal efecto si la palabra no está presente) se escribe en el error estándar y el shell, si no es interactivo, se cierra. De lo contrario, el valor del parámetro se sustituye.
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 :
¿Alguna idea sobre esta discusión? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
La esencia de la discusión es:
... Sin embargo, cuando lo hago shellcheck
(con la versión 0.4.1), recibo este mensaje:
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
¿Algún consejo sobre lo que debo hacer en este caso?
La respuesta corta es "haz lo que shellcheck
sugieras":
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
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 utiliza printf "%s\n"
en lugar de :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
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 que shellcheck
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.