De la subsección Sustitución de comandos en el estándar POSIX:
Command substitution allows the output of a command to be substituted in place of the command name itself.
Las sustituciones de comandos permiten una forma práctica de utilizar la salida de un comando sin necesidad de escribirlo primero en un archivo temporal y luego leerlo desde ese archivo. Esto se hace mejor si la salida del comando es una cadena corta en una sola línea.
Algunas personas usan sustituciones de comandos para recopilar la salida de un comando, aunque la cantidad de salida puede ser un documento de varias -líneas. Esto generalmente no es una buena manera de usar la sustitución de comandos. En su lugar, se debe utilizar el idioma estándar de Unix de pasar datos entre etapas de procesamiento utilizando canalizaciones o archivos temporales.
Ejemplos de sustituciones de comandos que utilizo:
Por ejemplo, para averiguar si el usuario actual está ejecutando el script como root:
if [ "$( id -u )" -ne 0 ]; then
echo 'This script requires root privileges, re-run with sudo' >&2
exit 1
fi
La sustitución del comando $(id -u)
se sustituirá con la salida de id -u
, que devolverá el UID (un número entero )del usuario actual.
Otro ejemplo. Estoy usando GnuPG para firmar confirmaciones git
. Para que GnuPG funcione correctamente, necesito establecer GPG_TTY
en el nombre del dispositivo terminal actual en el archivo de inicialización de mi shell interactivo. Hago esto con
export GPG_TTY="$( tty )"
Esto establece GPG_TTY
en algo como /dev/ttyp4
dependiendo de cuál sea el dispositivo terminal actual en la sesión de shell.
Otro ejemplo. Tengo un script que tiene que tratar la ejecución en una máquina Solaris como un caso especial:
case "$( uname -s )" in
SunOS)
# code specific for Solaris
;;
*)
# code for all other Unix platforms
esac
Otro ejemplo. El comando getconf PATH
devuelve la "ruta predeterminada" para el sistema actual.Lo uso en algunas circunstancias para restablecer la variable PATH
a un valor "predeterminado sensato":
PATH="$( getconf PATH )"
b
не будет завершено завершением a
.
$ { echo hello; } | { read message; printf 'got "%s"\n' "$message"; sleep 5; echo "ok, I'm done"; }
got "hello"
ok, I'm done
Здесьa
(функцияecho hello
)просто выводит строку и завершает работу. Правая сторона конвейера(b
)будет считывать строку, выводить ее, засыпать на некоторое время, а затем выполнять окончательный echo
перед завершением.
Если бы b
было завершено, когда a
было завершено, у него никогда не было бы времени сделать то, что нужно было сделать. Единственное, чтоb
не может здесь сделать, это прочитать больше данных со своего стандартного ввода (дополнительный read
в конце немедленно получит конец -из -файла ).
В другом сценарии (, не упомянутом в вопросе ), где b
завершается до того, как a
, a
получит сигнал PIPE
, если попытается записать к его стандартному выводу (через несуществующий -b
процесс )и завершить его (по умолчанию ).
Если он не пытался записать в канал, a
продолжал бы работать до тех пор, пока не будет выполнено.