Expansión del comando Bash

En la línea de comandos o dentro de los scripts de shell, hay tres formas básicas en que los comandos interactúan entre sí. La primera y la segunda forma es a través de y el entorno. La tercera forma es a través de un parámetro de un comando. Sin embargo, para que un comando interactúe con otro a través de parámetros, su salida resultante debe incluirse en la lista de parámetros. Ahí es donde entra en juego la expansión de mando o la sustitución de mando. ¡Aquí repasaremos todo lo que necesita saber sobre la sustitución de comandos para escribir scripts bash como un jefe!

Sustitución de mando

La sustitución de comandos es la característica básica del shell que permite que la salida de uno o más comandos se ejecuten en el lugar y se utilicen como expansión de variables como argumentos para otra expansión de comandos. En otras palabras, el resultado de los comandos se coloca en una variable anónima de corta duración y se sustituye por el comando circundante.

Sintaxis

Hay dos sintaxis o formas aceptables de realizar la sustitución de comandos en bash:

1) Sintaxis del signo de dólar y
2) sintaxis de comillas inversas.

En este punto, se presentan ambas formas sin mi opinión.

En la naturaleza, cuando los desarrolladores se ven obligados a escribir scripts bash, según mi experiencia, se utiliza una u otra sintaxis según las preferencias personales.

Sintaxis del signo de dólar

$( command )

En mi opinión, esta sintaxis es más fácil de leer, especialmente cuando se anidan sustituciones de comandos, sin mencionar que es menos propensa a errores.

Ejemplo 1: sustitución de comandos utilizando la sintaxis del signo de dólar para probar líneas en un archivo

La mayoría de los entornos Linux con comandos de Coreutils como cat y el también vienen equipados con un comando llamado wc, que le permite contar bytes, palabras y líneas en un archivo. Aquí lo usaremos para probar simplemente si un archivo contiene más de una cierta cantidad de líneas y luego hacer algo.

test ! $( seq 101 | wc -l ) -gt 100 || {
 echo do something
}

Notas

La expresión $ (seq 101 | wc -l) se evalúa como el entero 101 Como resultado, la expresión de prueba se convierte en, ¡prueba! 101 -gt 100. Además, podemos sacar el! operador de canalización y evaluación de la expresión de prueba restante. Es decir. Espero que esté de acuerdo en que la prueba 101 -gt 100 es efectivamente cierta. ¡Entonces nos quedamos con! verdadero en el lado izquierdo del operador de lista ||. ! lo verdadero se vuelve falso y falso || se convierte en realidad &amp&amp. Al final, nos quedamos con echo hacer algo.

Sintaxis de comillas invertidas

`command`

Si te gustan las comillas invertidas más que el dinero, ¡genial! Como es la naturaleza de la codificación, puede elegir escribir código de la forma que desee, a menos que deba cumplir con algunas pautas de estilo estrictas. Solo diré que puede tener dificultades para realizar la sustitución de comandos anidados.

Ejemplo 2: sustitución de comandos utilizando la sintaxis de comillas invertidas para incrustar la salida del comando anidado en el comando echo

Mantengamos las cosas simples y enviemos un mensaje indicando su nombre de usuario.

echo my username is `whoami`

Notas

Si su nombre de usuario es ‘linuxhint’, el comando anterior se evalúa como “mi nombre de usuario es linuxhint”.

Ahora que sabe cómo usar la sustitución de comandos, veamos formas de usarla.

Diversión con asignaciones y sustitución de comandos

A menudo, queremos asignar a una variable la salida de un comando. Esto se puede lograr mediante la sustitución de comandos.

variable=$( command args… )

Por ejemplo, en la asignamos al sujeto variable las letras del alfabeto de la siguiente manera.

Comandos

subject=$( echo {z..a} | tr -d ‘ ‘  )
echo ${subject}

Producción

zyxwvutsrqponmlkjihgfedcba

¡Conveniente! ¿No te alegra tener ahora la sustitución de mando?

Diversión con funciones y sustitución de comandos

Vamos a lanzar nuestra propia función de mapa que cuenta el número de palabras que contienen la letra a.

Primero, necesitamos una función que pruebe si alguna palabra contiene la letra a. En el siguiente fragmento, usaremos el reemplazo de patrones a través de la expansión de parámetros y el atributo entero en la asignación.

Comandos

has_a() {
  local instr=${1}
  local -i match=$( test ! ${instr//a} != ${instr} || echo 1 )
  echo ${match}
}

Si el resultado de reemplazar a de una cadena de entrada no es en sí mismo antes del reemplazo, decimos que la cadena de entrada contiene una letra a. En este caso, hacemos eco de 1. La sustitución de comando resultante está sujeta a asignación con el atributo de número entero. En el caso de la asignación de valor vacío, el valor asignado se toma como 0. Es decir, la función has_a devuelve 0 o 1 dependiendo de la presencia de la letra a en la cadena de entrada.

Aquí hay un vistazo rápido a nuestra función has_a en acción.

Comandos

has_a asdf
has_a sdf
has_a df
has_a f
has_a a

Producción

1
0
0
0
1

Luego, necesitamos una función para recorrer las palabras en una oración mientras aplicamos la función has_a que simplemente llamaremos map.

Comandos

map() {
 test ! ${#} -eq 1 || { true return }
 local function_name=${1}
 local first=${2}
 local rest=${@:3}
 echo $( ${function_name} ${first} ) $( map ${function_name} ${rest} )
}

Aquí hay un vistazo rápido a nuestra función de mapa en acción.

Comandos

map has_a a b c
map has_a {a..z}{a..z}
map has_a {a..b}{a..b}{a..b}

Producción

1 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0

¡Ahora estás en la matriz!

Todo lo que tenemos que hacer ahora es contar los 1 que llamaremos suma.

sum() {
 test ! ${#} -eq 1 || { echo 0 return }
 local -i first=${1}
 local rest=$( sum ${@:2} )
 first+=rest
 echo ${first}
}

¡Deberias hacer eso!

Aquí hay un vistazo rápido a nuestra función de suma en acción.

Comandos

sum $( map has_a {a..b}{a..b}{a..b} )
sum $( map has_a {a..z}{a..z} )
sum $( map has_a {a..c}{a..c} )

Producción

7
51
5

Más diversión con las asignaciones: función de configuración

Mientras estás aquí, divirtámonos un poco más con las asignaciones que exploran lo que me gusta llamar funciones de configuración, es decir, crearemos una función especializada para asignar un valor a una variable. Como ya sabrá, es posible que necesitemos usar la sustitución de comandos. Así es cómo.

Comandos

variable() {
 echo 1
}
setup-variable() {
 variable=$( variable )
}
setup() {
 setup-variable
}
main() {
 local variable=0
 setup
 echo ${variable}
}
main
echo ${variable:-empty}

Producción

1
empty

Ejercicios

  1. ¡Vuelva a escribir el comando en el Ejemplo 1 sin usar el operador de canalización!
  2. Reescriba el comando en el Ejemplo 2 usando la sintaxis del signo de dólar
  3. Escriba una función para contar las palabras sin a usando sum, map y has_a
  4. Escribe un Él / ella me ama, no programa ese bucle para siempre.
  5. Escriba una línea asignando a una variable el valor de la segunda fila y la tercera columna de un archivo CSV (ver )
  6. Escriba una línea asignando a una variable los consentimientos de un guión (Pista: use xxd)

TLDR

¡Fresco! ¡Puedes usar la expansión del comando bash ahora! Como era de esperar, poder expandir el código en comandos como mejor le parezca, le da ventaja cuando intenta resolver problemas del mundo real con la programación bash, además de producir código reutilizable. Codifique de manera responsable.

Gracias,

Leave a Comment

Your email address will not be published. Required fields are marked *

Hazlo Linux