¿Son `if` y` then` realmente programas

15

He leído que el punto y coma se usa para separar programas:

$ echo 3; ls -la

¿Significa eso if, theny elsehay programas separados aquí?

$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi

Esta pregunta no es sobre punto y coma.

Maxim Koretskyi
fuente
2
Posible duplicado de punto y coma en estructuras condicionales
Stephen Rauch
1
@StephenRauch No es realmente un duplicado. Además, es una consecuencia razonable de esa Q, como un intento de mayor comprensión.
user207673
Más formulación programática:[ $variable == abcdef ] && echo yes || echo no
Hagen von Eitzen
2
@HagenvonEitzen que no es estrictamente equivalente, si la declaración dentro de la primera rama falla, la segunda también se ejecutará.
Morgen
Posible duplicado de ¿Cuáles son los operadores de control y redirección de shell?
G-Man dice 'Restablecer a Monica' el

Respuestas:

26

Las ;declaraciones separadas (hablando libremente). Es (casi) siempre posible reemplazar a ;por una nueva línea.

Decir que ;separa dos programas, por lo tanto, ify thendebe ser "programas" es un poco demasiado simplista, ya que se puede hacer una declaración de palabras reservadas, funciones de shell, utilidades integradas y utilidades externas, y combinaciones de estas utilizando tuberías y operadores booleanos, etc. etc.

Ambas ify thenson palabras reservadas en la gramática del shell , no "programas". Aquí se usan para construir lo que técnicamente se llama un comando compuesto .

echoes probable que sea una utilidad incorporada en el shell (pero no es necesario que lo sea), y lses probable que sea una utilidad externa (o "programa" como usted dice).

Kusalananda
fuente
7

Si bien esa es una primera aproximación justa cuando uno comienza a aprender los conceptos básicos del uso de shells, en el nivel de "así es como se ejecuta un programa" y "así es como se ejecutan varios programas uno tras otro en una sola línea" , en realidad no es cierto.

La explicación más difícil de entender para un principiante pero más correcta es que el lenguaje shell es un lenguaje de computadora . Tiene una sintaxis . Esa sintaxis comprende varios elementos léxicos que incluyen (entre otras cosas) nuevas líneas, operadores, palabras y palabras reservadas.

if, then, else, Y fison todas las palabras reservadas . Tienen un significado particular al analizar la entrada que se le da a un shell, de acuerdo con su gramática . Del mismo modo, ;es un operador separador .

Por lo tanto, la entrada en el lenguaje shell es, en su conjunto, un programa informático interpretado por otro programa, un intérprete , el shell. Sus partes gramaticales individuales no son programas. El lenguaje de shell es una forma de especificar (otros) programas para que se ejecute el shell.

[no es un elemento léxico especial en la gramática de la shell, como un operador. Es una palabra ordinaria , que nombra uno de esos programas llamado [. Muchos shells tienen una versión integrada de este programa, combinada con el código del propio programa de shell, pero también puede encontrar un programa externo con este nombre en algún lugar como /bin/[o /usr/bin/[, qué programas que no sean shells pueden invocar. Igualmente, ]tampoco es un elemento léxico especial de shell. Es una palabra ordinaria, que se convierte en un argumento para el [programa. El [programa requiere que su argumento final, cuando se ejecuta, sea ], el cual procede a ignorar.

Otro programa similar nombrado en su pregunta es echo. Nuevamente, la mayoría de los shells tienen una versión incorporada de este programa. Pero, de nuevo, también hay una versión externa del programa, en algún lugar como /bin/echoo /usr/bin/echo, para que invoquen otros programas que no sean shells.

Un tercer programa nombrado en su pregunta es ls. Los shells generalmente no tienen versiones integradas de este programa, y ​​es un programa externo que se puede encontrar en algún lugar como /bin/lso /usr/bin/ls.

Para el shell Bourne Again, puede leer más sobre esto en las Características básicas del shell de la documentación de información del shell GNU Bourne Again. Otras conchas tienen diferentes gramáticas, naturalmente. La especificación Single Unix describe una sintaxis a la que se supone que se adhieren todos los shells conformes con POSIX (en sus modos conformes con POSIX).

Otras lecturas

  • " Gramática de Shell ". Lenguaje de comandos de shell . Especificaciones básicas Problema 7. El grupo abierto. IEEE 1003.1-2008. ISBN 1937218812.
  • test. Utilidades . Especificaciones básicas Problema 7. El grupo abierto. IEEE 1003.1-2008. ISBN 1937218812.
  • " Gramática de Shell ". El manual de Z Shell . versión 5.3.1. 2017
JdeBP
fuente
5

En realidad, no es descabellado pensar if, theny elsecomo los programas externos. De hecho, el shell Thompson en la primera edición original de Unix implementado ify gotocomo programas externos. Esto es posible porque el subproceso comparte descriptores de archivo con el proceso de shell, por lo que un goto (hacia adelante) solo tuvo que leer la entrada hasta que encuentra la etiqueta de destino y luego sale. Ver Thompson shell .

Johan Myréen
fuente
O de hecho ver Laurent Bercot's ify ifelse, que son parte de execline. Sin ifembargo, estos no están en la pregunta.
JdeBP
2
"En realidad no es descabellado pensar si, entonces y de otra manera, son programas externos" Bueno, lo es, porque no lo son.
Lightness compite con Monica el
2

Los theny elseno son programas. Las otras partes son. Observe que no hay ;'directamente después de ellos, pero después del comando preceden.

El [ ... ] es un comando, y necesita el ;if seguido por el comienzo de otro comando.

AFAIK, todas las estructuras de control en Bash, y probablemente la mayoría de los proyectiles * nix, son iguales. Son instrucciones para el intérprete. La prueba o condición, por otro lado, utiliza un programa / proceso que se "ejecuta" y son comandos. Como thenes parte de la línea que conduce al echocomando, debe estar separada por una nueva línea del comando anterior [ ... ]. No necesita separarse del comando que controla, el echo yes.

Legalmente, aunque feo y difícil de leer, también puedes hacer esto.

if [ $VARIABLE == abcdef ]
then echo yes
else echo no
fi

Tenga en cuenta que no hay necesidad de ningún ;control entre los controles aquí, aunque no estén en su propia línea.

Curiosamente, toda la estructura de control ( if ... fi) es un comando de shell, y la totalidad tiene que terminar con una nueva línea o un ;. La última línea no puede ser, fi echo donepero debe ser fi; echo done. Lo mismo que una asignación VARIABLE='abcdef'es un comando.

Aunque todas las estructuras de control son comandos, aún no son programas.

usuario207673
fuente
1

if, elif, then, Y fison todas las palabras clave reservadas utilizados para implementar uno de los constructos que se refiere como un comando compuesto en cáscara, lo que significa que no puede haber un comando (o más bien, otro comando) por cualquiera de esos nombres con cáscara. El propósito de ;en general no es separar los comandos, sino terminar una lista de comandos . Por ejemplo, la siguiente es una ifdeclaración válida :

if echo foo; echo bar; echo baz; then echo done; echo really done; fi

La condición de la ifdeclaración es la lista de comandos echo foo; echo bar; echo baz. El analizador sabe que la condición ha terminado porque then, que sigue inmediatamente a un punto y coma, no puede ser un comando porque es una palabra clave reservada. Por lo tanto, sabe que lo que sigue then es el inicio del cuerpo. Del mismo modo, fies una palabra clave reservada y, por lo tanto, no puede ser un tercer comando en el cuerpo de la ifdeclaración, pero marca el final del comando compuesto.

chepner
fuente
gracias, si se usa esto if program1 foo; program2 bar; program3 baz; , ¿qué estado del programa debería ser 0, para que el shell continúe then? ¿El último?
Maxim Koretskyi
Justo program3 baz. El estado de salida de una lista de comandos es el estado de salida del último comando en esa lista. Los otros dos pueden fallar sin afectar la condición.
chepner