Hay dos casos en los que me parece :
útil:
Asignaciones de variables predeterminadas
#!/bin/sh
# set VAR to "default value" if not already set in the environment
: "${VAR=default value}"
# print the value of the VAR variable. Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR}"
Esta es una manera conveniente de permitir a los usuarios de su script de shell anular una configuración sin editar el script. (Sin embargo, los argumentos de la línea de comandos son mejores porque no corre el riesgo de un comportamiento inesperado si el usuario coincide con la variable que usa en su entorno exportado). Así es como el usuario anularía la configuración:
VAR="other value" ./script
La ${VAR=value}
sintaxis dice establecer VAR
en value
si aún VAR
no está establecida, luego expandir al valor de la variable. Como todavía no nos importa el valor de la variable, se pasa como un argumento al comando no-op :
para descartarla.
Aunque :
es un comando no :
operativo, el shell realiza la expansión (¡no el comando!) Antes de ejecutar el :
comando, por lo que la asignación de variables aún ocurre (si corresponde).
También sería aceptable usar true
o algún otro comando en lugar de :
, pero el código se vuelve más difícil de leer porque la intención es menos clara.
El siguiente script también funcionaría:
#!/bin/sh
# print the value of the VAR variable. Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR=default value}"
Pero lo anterior es mucho más difícil de mantener. Si ${VAR}
se agrega una línea usando encima de esa printf
línea, se debe mover la expansión de asignación predeterminada. Si el desarrollador olvida mover esa tarea, se introduce un error.
Algo para poner en un bloque condicional vacío
Los bloques condicionales vacíos generalmente deben evitarse, pero a veces son útiles:
if some_condition; then
# todo: implement this block of code; for now do nothing.
# the colon below is a no-op to prevent syntax errors
:
fi
Algunas personas argumentan que tener un if
bloque verdadero vacío puede hacer que el código sea más fácil de leer que negar la prueba. Por ejemplo:
if [ -f foo ] && bar || baz; then
:
else
do_something_here
fi
es posiblemente más fácil de leer que:
if ! [ -f foo ] || ! bar && ! baz; then
do_something_here
fi
Sin embargo, creo que hay algunos enfoques alternativos que son mejores que un bloque verdadero vacío:
Ponga la condición en una función:
exotic_condition() { [ -f foo ] && bar || baz; }
if ! exotic_condition; then
do_something_here
fi
Ponga la condición dentro de llaves (o paréntesis, pero los paréntesis generan un proceso de subshell y cualquier cambio realizado en el entorno dentro de la subshell no será visible fuera de la subshell) antes de negar:
if ! { [ -f foo ] && bar || baz; } then
do_something_here
fi
Usar en ||
lugar de if
:
[ -f foo ] && bar || baz || {
do_something_here
}
Prefiero este enfoque cuando la reacción es simple, como afirmar condiciones:
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$@"; exit 1; }
[ -f foo ] && bar || baz || fatal "condition not met"