En V7 , [
se llamó a Unix , donde debutó el shell Bourne test
, y existió solo como /bin/test
. Entonces, el código que escribirías hoy como:
if [ "$foo" = "bar" ] ; then ...
hubieras escrito en su lugar como
if test "$foo" = "bar" ; then ...
Esta segunda notación todavía existe, y encuentro que está más claro lo que está sucediendo: está llamando a un comando llamado test
, que evalúa sus argumentos y devuelve un código de estado de salida que se if
usa para decidir qué hacer a continuación. Ese comando puede estar integrado en el shell, o puede ser un programa externo.
[
como alternativa a la que test
vino después.² Puede ser un sinónimo incorporado para test
, pero también se proporciona como /bin/[
en los sistemas modernos para proyectiles que no lo tienen como incorporado.
[
y test
puede implementarse usando el mismo código. Este es el caso para /bin/[
y /bin/test
en OS X, donde estos son enlaces duros al mismo ejecutable.³ Como resultado, la implementación ignora por completo el seguimiento ]
: no lo requiere si lo llama como /bin/[
, y no se queja si lo proporciona a /bin/test
.⁴
Nada de esa historia afecta [[
, porque nunca hubo un programa primordial llamado [[
. Existe únicamente dentro de esos shells que lo implementan como una extensión del shell POSIX .
Parte de la distinción entre "incorporado" y "palabra clave" se debe a este historial. También refleja el hecho de que las reglas de sintaxis para analizar [[
expresiones son diferentes, como se señala en la respuesta de John1024.
Notas al pie:
Cuando lo mira de esa manera, deja en claro por qué debe colocar espacios [
en los guiones de shell, a diferencia de la forma en que funcionan los paréntesis y corchetes en la mayoría de los otros lenguajes de programación. Si el analizador de comandos del shell permitiera if["$x"...
, también tendría que permitiriftest"$x"...
Sucedió alrededor de 1980. /bin/[
no existe en mi copia de Ancient Unix V7 de 1979, ni lo man test
documenta como un alias. En la entrada correspondiente a la página del manual que tengo en una copia preliminar del manual del Sistema III de 1980, está en la lista.
ls -i /bin/[ /bin/test
Pero no cuente con este comportamiento. La versión integrada de Bash [
requiere el cierre ]
, y su base de test
aplicación se quejará si no la proporcione.
La distinción entre comandos internos y externos también puede ser importante por otra razón: las dos implementaciones pueden comportarse de manera diferente. Este es el caso echo
en muchos sistemas. Debido a que solo hay una implementación, no es necesario hacer tal distinción para una palabra clave.
if "[" $x -eq 3 ]
funciona como se espera (porque Bash busca el comando llamado[
, y esto existe), peroif "[[" $x -eq 3 ]]
no no funciona (porque una vez más Bash busca de un comando del nombre apropiado, pero no hay[[
mando)./usr/bin/echo
, pero eso no significa que no sea una construcción .