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?
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?
Respuestas:
La explicación más simple sería, ya que en el manual se presenta como [[ expression ]]lo que tiene que haber espacio entre [[y expressiony 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:
El shell comienza a analizar su entrada dividiéndola en palabras. Las palabras, que son secuencias de caracteres, están delimitadas por espacios en blanco sin comillas (espacio, tabulación y nueva línea) o metacaracteres (<,>, |,;, &, (y)). Además de delimitar palabras, los espacios y las pestañas se ignoran, mientras que las líneas nuevas suelen delimitar comandos.
Entonces, como se indica en el manual, la secuencia de caracteres [[-ese considera una palabra shell. kshbuscaría dicho comando en la lista de incorporados y operadores especiales (como foro while), 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 -eparte en [[-ese consideraría una palabra shell, no un argumento en [[sí mismo. Sin embargo, [[se describe como comando compuesto, y el manual dice lo siguiente:
Los comandos compuestos se crean usando las siguientes palabras reservadas: estas palabras solo se reconocen si no se citan y si se usan como la primera palabra de un comando (es decir, no pueden ir precedidas de asignaciones de parámetros o redirecciones):
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 se kshreanude el desarrollo o parezca haber una bifurcación o clon (como mksho pdksh) alguien implementará una sintaxis sin espacio [[-e.
[[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?chares una palabra clave, pero aún no puede escribir charsomeletter = 'A';y esperar que el analizador se detenga después de ver char.
i--<=++j, y el compilador no tiene problemas para analizar eso como i -- <= ++ j.
_). Ksh tiene (como operador y (echo hello)analiza como ( echo hello ). Ha if, {, [[, y otras palabras clave , y ifx, {xy [[xson cada uno un token - como la forma charsomeletteres una ficha C. En contraste, un sin comillas (xen ksh son dos tokens, como cómo i--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:
$ help [
[: [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
Entonces [es equivalente a test(aparte de esperar un ]argumento al final). help testdará aún más detalles al respecto. Puedes comparar esto con help [[.
También hay una página de manual para el comando externo [( man \[).
En el caso de
if [[-e
[tampoco [[es un comando, allí. La palabra completa [[-ees.if [[-econvierte en una prueba de verdadero / falso. Entonces , ¿ existe un comando [[-e? ¿Es porque "[[-" es ambiguo?
Si. O no. [[-ees lo que es: nada que el shell entienda, por lo que supone que es su propio comando. ;-)
[[-ees un nombre de comando potencialmente válido (si se ve raro).
El espacio es un deliminador y es obligatorio. Como puedes ver en shellcheck:
$ shellcheck gmail-browse-msgs-algorithm.sh
In gmail-browse-msgs-algorithm.sh line 847:
[[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
^-- SC1035: You need a space after the [[ and before the ]].
(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 .
kshshell en la pregunta. Bash toma prestado [[operador kshy de esta tela de juicio su comportamiento es idéntico, pero me gustaría tener cuidado de supuestos ya que hay algunas diferencias significativas entre kshy bashel 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 que kshera un caparazón en el que shellcheckpodría encontrar errores. Espero que otros lo aprecien kshy bashsean 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, [o testdebe 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 eficiencia
ksh; 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 [ [[bash type [ [[:) 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, kshpero 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.
Dado que [[-epuede participar en la expansión de shell (se puede usar como
echo [[-e]*
para enumerar todos los archivos que comienzan con una letra entre [e einclusive), 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.
[[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 blanco