Hasta donde yo sé, [[
es una versión mejorada de [
, pero estoy confundido cuando lo veo [[
como una palabra clave y [
se muestra como incorporado.
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
TLDP dice
Un incorporado puede ser sinónimo de un comando del sistema con el mismo nombre, pero Bash lo reimplementa internamente. Por ejemplo, el comando Bash echo no es lo mismo que / bin / echo, aunque su comportamiento es casi idéntico.
y
Una palabra clave es una palabra reservada, token u operador. Las palabras clave tienen un significado especial para el shell, y de hecho son los componentes básicos de la sintaxis del shell. Como ejemplos, para, while, do y! son palabras clave De forma similar a un builtin, una palabra clave está codificada en Bash, pero a diferencia de un builtin, una palabra clave no es en sí misma un comando, sino una subunidad de una construcción de comando. [2]
¿No debería eso hacer ambos [
y [[
una palabra clave? ¿Hay algo que me falta aquí? Además, este enlace reafirma que ambos [
y [[
deben pertenecer al mismo tipo.
fuente
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 .Respuestas:
La diferencia entre
[
y[[
es bastante fundamental.[
es un comando Sus argumentos se procesan tal como se procesan los argumentos de cualquier otro comando. Por ejemplo, considere:El shell se expandirá
$name
y realizará tanto la división de palabras como la generación de nombre de archivo en el resultado, tal como lo haría con cualquier otro comando.Como ejemplo, lo siguiente fallará:
Para que esto funcione correctamente, se necesitan citas:
[[
es una palabra clave de shell y sus argumentos se procesan de acuerdo con reglas especiales. Por ejemplo, considere:La cáscara se expandirá
$name
, pero, a diferencia de cualquier otro comando, se llevará a cabo ni la división de palabras, ni generar nombres de archivos en el resultado. Por ejemplo, lo siguiente tendrá éxito a pesar de los espacios incrustados enname
:Resumen
[
es un comando y está sujeto a las mismas reglas que todos los demás comandos que ejecuta el shell.[[
Sin embargo, debido a que es una palabra clave, no un comando, el shell lo trata especialmente y opera bajo reglas muy diferentes.fuente
man bash
. Véanse, en particular, las secciones tituladas "EXPANSIÓN DE MANDO SIMPLE" y "EJECUCIÓN DE MANDO". Además de[[
, otros de bash palabras clave incluyenif
,then
,while
, y el 'caso'. No hay reglas generales para las palabras clave: cada palabra clave es un caso especial.man bash
incluye detalles para cada uno.En V7 ,
[
se llamó a Unix , donde debutó el shell Bournetest
, y existió solo como/bin/test
. Entonces, el código que escribirías hoy como:hubieras escrito en su lugar como
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 seif
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 quetest
vino después.² Puede ser un sinónimo incorporado paratest
, pero también se proporciona como/bin/[
en los sistemas modernos para proyectiles que no lo tienen como incorporado.[
ytest
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 permitieraif["$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 loman 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 detest
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.fuente
builtin
ykeyword
distinción entre[
y[[
cuando tanto proporciona la misma funcionalidad (excepto el hecho de que[[
viene con más características que[
)?[[
es una palabra clave que le permite a bash hacer cosas que no son posibles[
, por ejemplo, no es necesario citar mucho tiempo, porque el shell sabe que es una variable. Es decir, el procesamiento de la línea de comando se ve afectado cuando se usa una palabra clave, pero no cuando se usa una incorporada, eso sucede mucho más tarde.[
código incorporado, pero el código está comentado.cd
es un programa incorporado, pero no oculta nada (cd
no se puede implementar como un programa externo).[[
una palabra clave le permite al shell usar reglas de análisis especiales para sus argumentos. Por lo tanto, por desgracia, mi voto a favor va a John1024.[
originalmente era solo un comando externo, otro nombre para/bin/test
. Pero algunos comandos, como[
yecho
, se usan con tanta frecuencia en los scripts de shell que los implementadores del shell decidieron copiar el código directamente en el mismo shell, en lugar de tener que ejecutar otro proceso cada vez que se usan. Eso convirtió estos comandos en "incorporados", aunque aún puede invocar el programa externo a través de su ruta completa.[[
Llegó mucho más tarde. Aunque el builtin se implementa internamente dentro del shell, se analiza como los comandos externos. Como se explica en la respuesta de John1024, esto significa que las variables sin comillas se dividirán en palabras, y los tokens como>
y<
se procesan como redirección de E / S. Esto hizo que escribir expresiones de comparación complejas fuera inconveniente.[[
fue creado como sintaxis de shell, para que pueda analizarse ideosincráticamente. Dentro de las[[
variables no se dividen las palabras,<
y>
pueden usarse como operadores de comparación,=
pueden comportarse de manera diferente dependiendo de si se cita o no el siguiente parámetro, etc. Estas son todas las comodidades que hacen que sea[[
más fácil de usar que el[
comando / incorporado tradicional .No podían simplemente recodificar una
[
sintaxis como esta porque habría sido un cambio incompatible con millones de scripts. Al usar la nueva[[
sintaxis, que no existía anteriormente, podrían renovar totalmente la forma en que se usa de una manera compatible hacia arriba.Esto es similar a la evolución que resultó en la
$((...))
sintaxis de las expresiones aritméticas, que reemplazó principalmente alexpr
comando tradicional .fuente
El más nuevo
[[
enbash
es una optimización de[
.El clásico
[
tiene un gran inconveniente, cuando se usa con frecuencia para hacer una operación trivial: generará un nuevo proceso cada vez:(¡Crea un nuevo espacio de direcciones solo para comparar
0
y1
siempre!)Creo que un punto principal de la adición de
[[
fue hacer que la evaluación de la expresión dentro[
no generara un proceso adicional. Pero cómo[
funciona no podría cambiarse: crearía mucha confusión y problemas. Entonces, la optimización se implementó con un nuevo nombre, de una manera más eficiente, es decir, un comando integrado de shell.Se convirtió en palabra clave en la sintaxis de shell como efecto secundario.
En el momento en que
[
se usó primero, era la forma correcta de hacerlo con un proceso externo.fuente
[
originalmente era un comando externo, se agregó como una función integrada en el shell bastante pronto, probablemente para cuando se lanzó Unix System III y definitivamente antes de que se lanzara Unix System V. Por lo tanto, el "proceso adicional" no ha sido un problema durante años. Sin embargo, la sintaxis se mantuvo sin cambios: se trató como si fuera un comando externo.[
sea a la vez, eso significa algunos cambios ...