Por ejemplo, el siguiente comando no funciona:
if [[-e xyz]]; then echo File exists;fi
ksh da el siguiente error
[[-e: command not found
¿Es porque "[[-" es ambiguo?
command-line
syntax
ksh
AcBap
fuente
fuente
[[
es una palabra clave - presumiblemente árbol de análisis sintáctico de la cáscara requiere que las palabras clave deben ser delineadas por espacios en blancoRespuestas:
La explicación más simple sería, ya que en el manual se presenta como
[[ expression ]]
lo que tiene que haber espacio entre[[
yexpression
y cierre]]
. Pero, por supuesto, podemos intentar verlo más en profundidad. Los shells tienen una gramática algo compleja y dependen en gran medida del concepto de "división de palabras". En particular, el manual ksh (1) establece:Entonces, como se indica en el manual, la secuencia de caracteres
[[-e
se considera una palabra shell.ksh
buscaría dicho comando en la lista de incorporados y operadores especiales (comofor
owhile
), luego buscaría un comando externo, y voilà, ninguno encontrado, por lo tanto, hay un mensaje de error sobre el comando no encontrado.En este caso
[[
tampoco son metacaracteres especiales. Si lo fueran, la-e
parte en[[-e
se consideraría una palabra shell, no un argumento en[[
sí mismo. Sin embargo,[[
se describe como comando compuesto, y el manual dice lo siguiente:Por lo tanto, para
[[
ser reconocido como un comando compuesto, debe ser la primera palabra de un comando o lista de comandos, lo que por definición previa de una "palabra" implica que debe estar separado por espacios, tabulaciones o líneas nuevas de otros palabras / argumentos.Has preguntado en los comentarios : "¿Por qué el analizador no puede detenerse tan pronto como encuentra el patrón" [["y lo trata como el inicio de un comando condicional?" La respuesta corta probablemente se deba a que 1) influye en la
[
sintaxis, ya que originalmente era un comando externo, y para el cumplimiento estándar POSIX existe como comando externo incluso hoy, y 2) porque el analizador de shell está construido de esta manera. El analizador de shell puede reconocer otros caracteres especiales no delimitados por espacios:echo $((2+2))
y(echo foobar)
funciona perfectamente bien. Tal vez en el futuro cuando seksh
reanude el desarrollo o parezca haber una bifurcación o clon (comomksh
opdksh
) alguien implementará una sintaxis sin espacio[[-e
.Ver también:
[[
se denomina "palabra reservada" (consulte la sección 2.9 del lenguaje de comandos de Shell ). Por definición POSIX, la palabra reservada tiene que estar delimitada por espacios. Por el contrario,(
es un operador, y los estados estándar en la sección 2.9 "las representaciones incluyen el espacio entre los tokens en algunos lugares donde<blank>
s no sería necesario (cuando uno de los tokens es un operador)". Vea la discusión relacionada: Gramática de shell POSIX: ¿por qué Brace Group necesita el primer espacio pero Subshell no?fuente
char
es una palabra clave, pero aún no puede escribircharsomeletter = 'A';
y esperar que el analizador se detenga después de verchar
.i--<=++j
, y el compilador no tiene problemas para analizar eso comoi -- <= ++ j
._
). Ksh tiene(
como operador y(echo hello)
analiza como( echo hello )
. Haif
,{
,[[
, y otras palabras clave , yifx
,{x
y[[x
son cada uno un token - como la formacharsomeletter
es una ficha C. En contraste, un sin comillas(x
en ksh son dos tokens, como cómoi--
son dos tokens en C. Lo que conceptualmente significa ser un operador difiere entre los shells de estilo Bourne (como ksh) y C. Pero Peter A. Schneider señaló un similitud léxica real .Es importante tener en cuenta que
[
es un comando, y la palabra clave de shell[[
en bash y ksh se basa en[
.[[
se usa de manera similar a[
. A veces incluso se puede sustituir[
]
con[[
]]
sin cambio en el comportamiento. Con[
, como cualquier comando, un espacio es obligatorio entre el comando y sus argumentos. Lo mismo se aplica a[[
.Solíamos tener solo
/usr/bin/[
. Ahora la mayoría de los shells se han[
incorporado para la eficiencia, pero la sintaxis es la misma. En los depósitos que proporcionan[[
, funciona como una alternativa más versátil para[
.Aquí está la descripción de
[
en bash:Entonces
[
es equivalente atest
(aparte de esperar un]
argumento al final).help test
dará aún más detalles al respecto. Puedes comparar esto conhelp [[
.También hay una página de manual para el comando externo
[
(man \[
).En el caso de
[
tampoco[[
es un comando, allí. La palabra completa[[-e
es.if [[-e
convierte en una prueba de verdadero / falso. Entonces , ¿ existe un comando[[-e
?Si. O no.
[[-e
es lo que es: nada que el shell entienda, por lo que supone que es su propio comando. ;-)fuente
[[-e
es un nombre de comando potencialmente válido (si se ve raro).El espacio es un deliminador y es obligatorio. Como puedes ver en
shellcheck
:(Tanto ksh como bash admiten
[[
y no funcionan sin el espacio. Shellcheck proporciona exactamente esa salida con scripts ksh y bash similares que contienen esa línea con errores).Por qué se necesitan delimitadores tiene que ver con tokens y léxicos .
fuente
ksh
shell en la pregunta. Bash toma prestado[[
operadorksh
y de esta tela de juicio su comportamiento es idéntico, pero me gustaría tener cuidado de supuestos ya que hay algunas diferencias significativas entreksh
ybash
el comportamiento y el funcionamiento interno. Eso es solo porque shellcheck funciona en script bash, puede que no sea necesariamente una herramienta apropiada para scripts ksh. Solo algo a tener en cuenta al acercarse a diferentes proyectiles[[
reglas integradas. De ninguna manera deduje queksh
era un caparazón en el queshellcheck
podría encontrar errores. Espero que otros lo aprecienksh
ybash
sean dos intérpretes diferentes. Gracias por mencionar eso. También vale la pena señalar que[[
es un bash incorporado, mientras que[
es un comando externo.[
también es una función integrada en bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Pero no está lejos,[
otest
debe ser un comando externo. En los días de Bourne Shell original[
era, de hecho, un comando externo, y todavía existe hoy en día/usr/bin/[
porque POSIX requiere que sea un comando externo pubs.opengroup.org/onlinepubs/009695399/utilities/test.html POSIX requiere muy pocos ser incorporado pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Builtin[
es para la eficienciaksh
; usar un hashbang o-s ksh
. Btw, ksh y bash se han[[
"incorporado", pero es una palabra clave , a diferencia de[
, que es un shell incorporado . (ksh :;whence -v [ [[
bashtype [ [[
:) Los comandos internos y externos son sintácticamente similares. Una forma diferente[[
de esto[
es que[[
suprime algunas expansiones en sus argumentos, lo que no podría ser como un componente integrado, al igual{
que no podría agruparse si fuera un elemento integrado. Esta puede ser la razón por la cual{x
(o[[x
) ser una ficha se siente extraño. Creo que es correcto decir que las palabras clave y las palabras clave son léxicas pero no sintácticamente similares. @SergiyKolodyazhnyy[[
puede ser un comando externo! Es decir, puede ser un programa y no una sintaxis compatible con su shell directamente. Sería posible soportar una sintaxis sin espacio,ksh
pero fallaría en sistemas con sistema externo,[[
por lo que por razones de compatibilidad es mejor mantener el espacio requerido.BusyBox se proporciona
[[
como un comando externo , por ejemplo.fuente
Dado que
[[-e
puede participar en la expansión de shell (se puede usar comopara enumerar todos los archivos que comienzan con una letra entre
[
ee
inclusive), sería un completo desastre si[
y si]
los caracteres especiales no participaran en la división normal de palabras gobernada por espacios en blanco.fuente