¿Cuál es el propósito de: (dos puntos) GNU Bash incorporado?
¿Cuál es el propósito de un comando que no hace nada, siendo poco más que un líder de comentario, pero que en realidad es un shell integrado en sí mismo?
Es más lento que insertar un comentario en sus scripts en aproximadamente un 40% por llamada, lo que probablemente varía mucho según el tamaño del comentario. Las únicas razones posibles que puedo ver son estas:
# poor man's delay function
for ((x=0;x<100000;++x)) ; do : ; done
# inserting comments into string of commands
command ; command ; : we need a comment in here for some reason ; command
# an alias for `true'
while : ; do command ; done
Supongo que lo que realmente estoy buscando es qué aplicación histórica podría haber tenido.
Históricamente , los shells Bourne no tenían comandos integrados true
y . en cambio, simplemente tenía un alias y algo así como .false
true
:
false
let 0
:
es ligeramente mejor que true
en cuanto a portabilidad a antiguos shells derivados de Bourne. Como ejemplo simple, considere no tener ni el !
operador de tubería ni el ||
operador de lista (como era el caso de algunos shells Bourne antiguos). Esto deja la else
cláusula de la if
declaración como el único medio para bifurcar según el estado de salida:
if command; then :; else ...; fi
Dado que if
requiere una cláusula que no esté vacía then
y los comentarios no cuentan como no vacíos, :
sirve como una opción no operativa.
Hoy en día (es decir, en un contexto moderno) normalmente puedes utilizar :
o true
. Ambos están especificados por POSIX y algunos resultan true
más fáciles de leer. Sin embargo, hay una diferencia interesante: :
es el llamado POSIX integrado especial , mientras que true
es un integrado normal .
Se requieren elementos incorporados especiales en el armazón; Las funciones integradas regulares sólo están integradas "normalmente", pero no están estrictamente garantizadas. Por lo general, no debería haber un programa normal
:
con el nombre de la funcióntrue
en PATH de la mayoría de los sistemas.Probablemente la diferencia más crucial es que con los integrados especiales, cualquier variable establecida por el integrado, incluso en el entorno durante la evaluación de un comando simple, persiste después de que se completa el comando, como se demuestra aquí usando ksh93:
$ unset x; ( x=hi :; echo "$x" ) hi $ ( x=hi true; echo "$x" ) $
Tenga en cuenta que Zsh ignora este requisito, al igual que GNU Bash, excepto cuando opera en modo de compatibilidad POSIX, pero todos los demás shells principales "derivados de POSIX sh" cumplen con esto, incluidos dash, ksh93 y mksh.
Otra diferencia es que los integrados regulares deben ser compatibles con
exec
(lo que se demuestra aquí usando Bash):$ ( exec : ) -bash: exec: :: not found $ ( exec true ) $
POSIX también señala explícitamente que
:
puede ser más rápido quetrue
, aunque, por supuesto, esto es un detalle específico de la implementación.
Lo uso para habilitar/deshabilitar fácilmente comandos variables:
#!/bin/bash
if [[ "$VERBOSE" == "" || "$VERBOSE" == "0" ]]; then
vecho=":" # no "verbose echo"
else
vecho=echo # enable "verbose echo"
fi
$vecho "Verbose echo is ON"
De este modo
$ ./vecho
$ VERBOSE=1 ./vecho
Verbose echo is ON
Esto lo convierte en un guión limpio. Esto no se puede hacer con '#'.
También,
: >afile
es una de las formas más sencillas de garantizar que 'un archivo' exista pero tenga una longitud de 0.
Una aplicación útil :
es si solo está interesado en usar expansiones de parámetros para sus efectos secundarios en lugar de pasar su resultado a un comando.
En ese caso, utilice la expansión del parámetro como argumento para cualquiera de los dos :
o false
dependiendo de si desea un estado de salida de 0 o 1. Un ejemplo podría ser
: "${var:=$1}"
Dado que :
es una función incorporada, debería ser bastante rápido.