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
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.
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 &&. Al final, nos quedamos con echo hacer algo.
Sintaxis de comillas invertidas
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.
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.
Por ejemplo, en la asignamos al sujeto variable las letras del alfabeto de la siguiente manera.
Comandos
echo ${subject}
Producción
¡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
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 sdf
has_a df
has_a f
has_a a
Producción
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
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..z}{a..z}
map has_a {a..b}{a..b}{a..b}
Producción
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.
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..z}{a..z} )
sum $( map has_a {a..c}{a..c} )
Producción
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
echo 1
}
setup-variable() {
variable=$( variable )
}
setup() {
setup-variable
}
main() {
local variable=0
setup
echo ${variable}
}
main
echo ${variable:-empty}
Producción
empty
Ejercicios
- ¡Vuelva a escribir el comando en el Ejemplo 1 sin usar el operador de canalización!
- Reescriba el comando en el Ejemplo 2 usando la sintaxis del signo de dólar
- Escriba una función para contar las palabras sin a usando sum, map y has_a
- Escribe un Él / ella me ama, no programa ese bucle para siempre.
- Escriba una línea asignando a una variable el valor de la segunda fila y la tercera columna de un archivo CSV (ver )
- 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,