Tuberías y sustitución de comandos
Como hemos visto, el valor de retorno de un comando, tomado estrictamente, es solo un pequeño entero no negativo destinado a indicar el éxito o el fracaso. Su salida real es lo que escribe en el flujo de salida estándar. De forma predeterminada, el texto escrito en el flujo de salida estándar se imprime en el terminal, pero hay algunas formas en que se puede "capturar" y usar como el verdadero valor de retorno del comando.
Cuando una secuencia de comandos se vincula entre sí en una tubería, la salida de cada comando se pasa como entrada al siguiente. Esta es una técnica muy poderosa, ya que nos permite combinar varios programas de utilidad pequeños para crear algo complejo.
Sustitución de comandos
La sustitución de comandos es un poco como expansión de variable, pero ejecuta un comando y captura su salida, en lugar de simplemente recuperar el valor de una variable. Por ejemplo, considere nuestro ejemplo de get_password anterior:
Realmente no hay razón para que la persona que llama deba guardar la contraseña en una variable.
Si get_password simplemente imprimió la contraseña en su salida estándar, entonces la persona que llama podría usar la sustitución de comandos y usarla directamente:
Para evaluar "$ (get_password)" , Bash ejecuta el comando get_password en una subshell, capturando su salida estándar y reemplaza $ (get_password) por la salida capturada.
Además de la notación $ (...) , también se admite una notación más antigua (con comillas inversas), y aún se encuentra con bastante frecuencia. Las dos notaciones tienen el mismo efecto, pero la sintaxis de es más restrictiva y, en casos complejos, puede ser más complicado acertar.
La sustitución de comandos permite anidar como vemos . Se permite, expresiones "$ (b" $ (c) ")" . (es decir ,ejecuta el comando c , usando su salida como un argumento para b , y usando la salida de eso como un argumento para a .)
Una sustitución de comando puede contener una secuencia de comandos, en lugar de un solo comando de modo que se captura la salida de todos estos comandos.
Como hemos visto anteriormente, se pueden usar puntos y coma en lugar de líneas nuevas para separar los comandos, lo cual es particularmente común en la sustitución de comandos.
Una sustitución de comando p uede incluso contener asignaciones de variables y definiciones de funciones (aunque, como los comandos sustituidos se ejecutan dentro de una subshell, las asignaciones de variables y las definiciones de funciones dentro del comando no se verán fuera de ella; solo son útiles si se usan dentro de los comandos sustituidos ).
Aritmética de shell
Las expresiones aritméticas en Bash se modelan estrechamente en las de C, por lo que son muy similares a las de otros lenguajes derivados de C, como C ++, Java, Perl, JavaScript, C # y PHP.
Una diferencia importante es que Bash solo admite aritmética de enteros (números enteros), no aritmética de punto flotante (decimales y fracciones); Por ejemplo algo como 3 + 4 significa lo que esperarías (7), pero algo como 3.4 + 4.5 es un error de sintaxis. Algo así como 13/5 está bien, pero realiza una división de enteros, por lo que se evalúa en 2 en lugar de en 2.6.
Expansión aritmética
Quizás la forma más común de usar expresiones aritméticas es en la expansión aritmética , donde el resultado de una expresión aritmética se usa como un argumento para un comando
. La expansión aritmética se denota $ ((...)) . Por ejemplo, este comando:
impresiones 19 .
expr (en desuso)
Otra forma de usar expresiones aritméticas es mediante el programa Unix "expr", que era popular antes de que Bash admitiera las matemáticas. Similar a la expansión aritmética, este comando:
impresiones 19 .
Tenga en cuenta que el uso de "expr" requiere un carácter de escape "\" antes del operador de multiplicación "*" y los paréntesis. Tenga en cuenta los espacios entre los símbolos de cada operador, incluidos los paréntesi s.
Operadores numéricos
Además de las notaciones familiares + (adición) y - (resta), las expresiones aritméticas también son compatibles con * (multiplicación), / (división entera, descrita anteriormente), % (división de módulo, la operación "resto"; por ejemplo, 11 dividido por 5 es 2 el resto 1, entonces 11% 5 es 1 ), y ** ("exponenciación", es decir, involución; por ejemplo, 2 4 = 16, entonces 2 ** 4 es 16 ).
Los operadores + y - , además de sus sentidos "binarios" (dos operandos) de "suma" y "resta", tienen sentidos "unarios" (un operando) de "positivo" y "negativo". Unary + tiene básicamente ningún efecto; unary - invierte el signo de su operando. Por ejemplo, - (3 * 4) evalúa a -12 , y - (- (3 * 4)) evalúa a 12 .
Referente a variables
Dentro de una expresión aritmética, se puede hacer referencia a las variables de shell directamente, sin usar expansión variable (es decir, sin el signo de dólar $ ).
Por ejemplo, esto:
impresiones 35 . (Tenga en cuenta que primero se evalúa i , que produce 5 y luego se multiplica por 7. Si hubiéramos escrito $ i en lugar de i , se habría realizado una mera sustitución de cadenas; 7 * 2 + 3 es igual a 14 + 3, es decir, 17 - Probablemente no sea lo que queremos.
El ejemplo anterior se muestra usando "expr":
impresiones 35 .
Asignación a variables
Las variables de shell también se pueden asignar dentro de una expresión aritmética. La notación para esto es similar a la asignación de variables regulares, pero es mucho más flexible.
Por ejemplo, el ejemplo anterior podría reescribirse así:
excepto que esto establece $ i a 5 en lugar de a 2 + 3 .
Tenga en cuenta que, aunque la expansión aritmética parece un poco a la sustitución de comandos, se no se ejecuta en un subnivel; este comando realmente establece $ i a 5 , y los comandos posteriores pueden usar el nuevo valor. (Los paréntesis dentro de la expresión aritmética son solo el uso matemático normal de paréntesis para controlar el orden de las operaciones).
Además del operador de asignación simple = , Bash también admite operadores compuestos como + = , - = , * = , / = y % = , que realizan una operación seguida de una asignación. Por ejemplo, ((i * = 2 + 3)) es equivalente a ((i = i * (2 + 3))) . En cada caso, la expresión en su conjunto se evalúa al nuevo valor de la variable; por ejemplo, si $ i es 4 , entonces ((j = i * = 3)) establece tanto $ i como $ j en 12 .
Por último, Bash soporta operadores de incremento y decremento.
E l operador incremental ++ incrementa el valor de una variable en 1; si precede al nombre-variable (como el operador "pre-incremento"), entonces la expresión se evalúa al nuevo valor de la variable , y si sigue al nombre-variable (como el operador "post-incremento"), entonces la expresión se evalúa al valor antiguo de la variable .
Por ejemplo, si $ i es 4 , entonces ((j = ++ i)) establece tanto $ i como $ j en 5 , mientras que ((j = i ++)) establece $ i en 5y $ j a 4 . El operador de disminución - es exactamente el mismo, excepto que disminuye el valor de la variable en 1. La reducción previa y posterior de la reducción son completamente análogas al incremento previo y al incremento posterior.
Las expresiones aritméticas como sus propios comandos
Un comando puede consistir completamente en una expresión aritmética, usando cualquiera de las siguientes sintaxis:
Cualquiera de estos comandos establecerá $ i en 5 . Ambos estilos de comando devuelven un estado de salida de cero ("exitoso" o "verdadero") si la expresión se evalúa como un valor distinto de cero, y un estado de salida de uno ("falla" o "falso") si la expresión se evalúa como cero. Por ejemplo, esto:
imprimirá esto:
zero non-zero
La razón de este comportamiento contraintuitivo es que en C, cero significa "falso" y los valores distintos de cero (especialmente uno) significan "verdadero". Bash mantiene ese legado dentro de las expresiones aritméticas, luego lo convierte en la convención habitual de Bash al final.
El operador de coma
Las expresiones aritméticas pueden contener múltiples sub-expresiones separadas por comas , . El resultado de la última sub-expresión se convierte en el valor general de la expresión completa. Por ejemplo, esto:
De hecho , la función incorporada admite múltiples expresiones directamente sin necesidad de una coma; por lo tanto, los siguientes tres comandos son equivalentes:
let 'i = 2, j = 2 + i, i * j'
Operadores de comparación, booleanos y condicionales
Las expresiones aritméticas son compatibles con los operadores de comparación de enteros < , > , <= (significado ≤), > = (significado ≥), == (significado =) y ! = (Significado). Cada uno evalúa a 1 para "verdadero" o 0 para "falso".
También son compatibles con los operadores booleanos:
Aparte de que utilizan cero para significar valores "falsos" y valores distintos de cero para significar "verdaderos", son como los operadores , , y que hemos visto fuera de expresiones aritméticas. Al igual que esos operadores, estos son operadores "abreviados" que no evalúan su segundo argumento si su primer argumento es suficiente para determinar un resultado. Por ejemplo, (j = 2))) no evaluará el parte, y por lo tanto no establecerá $ j en 2 , porque el operando izquierdo de & es cero ("falso").
¿Y soportan el operador condicional . Este operador evalúa e1 y devuelve su resultado, si b es distinto de cero; de lo contrario, evalúa e2 y devuelve su resultado.
Estos operadores se pueden combinar de formas complejas:
Aritmética de bucles
Arriba, vimos un estilo de for-loop, que se veía así:
# imprimir todos los enteros del 1 al 20:
Bash también admite otro estilo, modelado en los bucles for de C y lenguajes relacionados, usando aritmética de shell:
# imprimir todos los enteros del 1 al 20:
Este bucle for utiliza tres expresiones aritméticas separadas, separadas por punto y coma ; (y no comas , son expresiones completamente separadas, no solo subexpresiones):
- La primera es una expresión de inicialización, se ejecuta antes de que comience el bucle.
- El segundo es una expresión de prueba; se evalúa antes de cada posible iteración del bucle (incluida la primera), y si se evalúa a cero ("falso"), entonces el bucle sale.
- El tercero es una expresión de conteo; Se evalúa al final de cada iteración de bucle. En otras palabras, este bucle for es exactamente equivalente a este bucle while:
# imprimir todos los enteros del 1 al 20:
pero, una vez que se acostumbre a la sintaxis, se hace más claro lo que está sucediendo.
Operadores bitwise
Además de aritméticas y booleanas operadores regulares, Bash también ofrece a los operadores bit a bit "", significa que los operadores que operan sobre números enteros qua cadenas de bits en lugar de qua enteros.
Si aún no está familiarizado con este concepto, puede ignorarlo de manera segura.
Al igual que en C, los operadores bitwise son :
Literales enteros
Una constante entera se expresa como un entero literal . Ya hemos visto muchos de estos; 34 , por ejemplo, es un literal entero que denota el número 34.
Todos los ejemplos anteriores han sido decimales (base diez) literales enteros, que es el valor predeterminado; pero, de hecho, los literales pueden expresarse en cualquier base en el rango 2-64, utilizando el notación # (la propia base se expresa en base diez).
Por ejemplo, esto:
echo $ (( 12 )) # usa el valor predeterminado de base diez (decimal)echo $ (( 10 # 12 )) # especifica explícitamente base diez (decimal)echo $ (( 2 # 1100 )) # base dos (binario)echo $ (( 8 # 14 )) # base ocho (octal)echo $ (( 16 # C )) # base dieciseis (hexadecimal)eco $ (( 8 + 2 # 100 )) # ocho en base diez (decimal), más cuatro en base dos (binario)
Imprimirá 12 seis veces. (Tenga en cuenta que esta notación solo afecta a cómo se interpreta un literal entero. El resultado de la expansión aritmética todavía se expresa en base diez, independientemente).
Para las bases 11 a 36, las letras inglesas A a Z se usan para los valores de dígitos 10 a 35. Esto no distingue entre mayúsculas y minúsculas. Sin embargo, para las bases 37 a 64, son las letras inglesas en minúsculas las que se usan para los valores de dígitos 10 a 35, mientras que las letras mayúsculas se usan para los valores de dígitos 36 a 61, el signo at @ se usa para las cifras el valor 62, y el subrayado _ se usa para el valor de dígitos 63. Por ejemplo, 64 # @ A3 indica 256259 ( 62 × 64 2 + 36 × 64 + 3 ).
También hay dos notaciones especiales: el prefijo de un literal con 0 indica la base ocho (octal), y el prefijo de 0x o 0X indica la base dieciséis (hexadecimal). Por ejemplo, 030 es equivalente a 8 # 30 , y 0x6F es equivalente a 16 # 6F .
Variables enteras
Una variable se puede declarar como una variable entera, es decir, su "atributo entero" se puede "establecer", usando esta sintaxis:
Después de ejecutar el comando anterior, cualquier asignación subsiguiente a n hará que el lado derecho se interprete automáticamente como una expresión aritmética. Por ejemplo, esto:
Es más o menos equivalente a esto:
excepto que la primera versión declare -in
continuará afectando las tareas posteriores también.
En la primera versión, note el uso de comillas en el lado derecho de la tarea. Si hubiéramos escrito n = 2 + 3> 4 , habría significado "ejecutar el comando + con el argumento 3 , pasando la variable de entorno n configurada a 2 y redirigiendo la salida estándar al archivo 4 "; es decir, establecer el atributo entero de una variable no afecta el análisis global de las declaraciones de asignación, sino que simplemente controla la interpretación del valor que finalmente se asigna a la variable.
Podemos "anular" el atributo entero de una variable, desactivando este comportamiento, usando el comando opuesto:
El comando declare incorporado también tiene otros usos: hay algunos otros atributos que una variable puede tener, y declare tiene algunas otras características además de activar y desactivar los atributos. Además, algunas de sus propiedades destacan:
- Al igual que con local y export , el argumento puede ser una asignación de variable; por ejemplo, establece el atributo entero de $ n y lo establece en 5 .
- Al igual que con local y export , se pueden especificar múltiples variables (y / o asignaciones) a la vez; por ejemplo,
declare -i n=2+3
establece tanto el atributo entero de $ m como el de $ n . - Cuando se usa dentro de una función, declare implícitamente localiza la variable (a menos que la variable ya sea local), lo que también tiene el efecto de desarmarla localmente (a menos que se use la sintaxis de asignación).
Aritmética no entera
Como se mencionó anteriormente, Bash shell arithmetic solo admite aritmética de enteros. Sin embargo, los programas externos a menudo se pueden usar para obtener una funcionalidad similar para valores no enteros.
En particular, la utilidad de Unix común bc se usa a menudo para esto. El siguiente comando:
impresiones 5.6 .
No hace falta decir que, dado que bc no está tan estrechamente integrado con Bash como lo es la aritmética de shell, no es tan conveniente; por ejemplo, algo como esto:
# imprimir las potencias de dos, de 1 a 512:
sería, para soportar no enteros, convertirse en algo como esto:
# imprimir los poderes de la mitad, de 1 a 1/512:
Parte de esto se debe a que ya no podemos usar un aritmética for-loop; parte de esto se debe a que hacer referencia a las variables y asignarlas a las variables es más complicado ahora (ya que bc no es consciente de las variables de la shell, solo de las suyas, no relacionadas); y parte de ello se debe a que bc se comunica con el shell solo a través de entrada y salida.
!Y esto es todo por hoy!Pero no se preocupe en proximos post trataremos otrso temas como entrada/salida, funcionaes complejas y mucho mas
Mas informacion en https://en.wikibooks.org/wiki/Bash_Shell_Scripting