Subshells de Linux avanzados con ejemplos

Subshells de Linux avanzados con ejemplos

Si lee nuestras subshells de Linux anteriores para principiantes con un artículo de ejemplos, o ya tiene experiencia con subshells, sabe que las subshells son una forma poderosa de manipular los comandos bash en línea, y de manera sensible al contexto.

En este tutorial aprenderás:

  • Cómo crear comandos de subshell más avanzados
  • Donde puede emplear subshells más avanzadas en su propio código
  • Ejemplos de comandos de subshell más avanzados
Subshells de Linux avanzados con ejemplos

Requisitos y convenciones de software utilizados

Requisitos de software y convenciones de línea de comandos de Linux
Categoría Requisitos, convenciones o versión de software utilizada
Sistema Independiente de la distribución de Linux
Software Línea de comando bash, sistema basado en Linux
Otro Cualquier utilidad que no esté incluida en el shell bash de forma predeterminada se puede instalar utilizando sudo apt-get instalación de utilidad de utilidad (o yum en lugar de apt-get)
Convenciones # - requiere que los comandos de Linux se ejecuten con privilegios raíz directamente como un usuario raíz o mediante el uso de sudo dominio
$-Requiere que los comandos de Linux se ejecuten como un usuario regular no privilegiado

Ejemplo 1: Contando archivos

$ if [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; luego hacer eco "encontró uno o más ocurrencias de archivos [A-Z]*!"; Fi 


Aquí tenemos un si Declaración con el primer valor de comparación de una subshell. Esto funciona bien y proporciona una gran cantidad de flexibilidad cuando se trata de escribir si declaraciones. Es diferente que el binario (verdadero o falso) como la operación de, por ejemplo, un Si grep -q 'search_term' ./Docfile.TXT declaración. Más bien, se evalúa per se Como una comparación estándar (coincidente con el más grande -GT 0 cláusula).

La subshell intenta a los archivos de la lista de directorio nombrados [Arizona]*, i.mi. archivos que comienzan con al menos una letra en el Arizona rango, seguido de cualquier personaje posterior. Es seguro de error agregando 2>/dev/nulo - i.mi. Cualquier error mostrado (en stderr - la salida de error estándar, significada por el 2) será redirigido > a /dev/nulo - i.mi. el dispositivo nulo de Linux, y así ignorado.

Finalmente pasamos la entrada de LS a WC -L que nos contará cuántas líneas (o en este caso, archivos) fueron vistos. Si el resultado fue más de 0, se muestra la nota informativa.

Observe cómo se varía el contexto en el que está operando la subshell. En primer lugar, en este caso, la subshell está trabajando dentro del directorio de trabajo actual (I.mi. $ PWD) que es notablemente también el valor predeterminado i.mi. Subshells Por defecto, comienzan con su propio entorno Pwd Establecer en el directorio de trabajo actual. En segundo lugar, la subshell está trabajando dentro del contexto de un si declaración.

Este comando genera ninguna salida, ya que se está ejecutando dentro de un directorio vacío. Sin embargo, tenga en cuenta que el hecho de que no se genera salida también significa que nuestra supresión de errores está funcionando. Verifiquemos eso:

$ if [$ (ls [a -z]* | wc -l) -gt 0]; luego hacer eco "encontró uno o más ocurrencias de archivos [A-Z]*!"; fi ls: no puede acceder '[a-z]*': no ​​hay dicho archivo o directorio 

Podemos ver cómo la eliminación de la supresión de errores funcionó en el ejemplo anterior. A continuación, creemos un archivo y veamos cómo funciona nuestro Liner:

$ touch a $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; luego hacer eco "encontró uno o más ocurrencias de archivos [A-Z]*!"; Fi encontró uno o más ocurrencias de archivos [A-Z]*! 


Genial, parece que nuestro guión de una línea funciona bien. A continuación, agregemos un archivo secundario y veamos si podemos mejorar el mensaje

$ touch b $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; luego hacer eco "encontró uno o más ocurrencias de archivos [A-Z]*!"; Fi encontró uno o más ocurrencias de archivos [A-Z]*! $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; luego echo "encontró exactamente $ (ls [a-z]* 2>/dev/null | wc -l) ocurrencias de archivos [a-z]*!"; Fi encontró exactamente 2 ocurrencias de archivos [A-Z]*! 

Aquí vemos que agregar un segundo archivo (por toque B) no hace ninguna diferencia (como se ve en el primero si comando), a menos que cambiemos la salida para informar realmente cuántos archivos se encontraron insertando una subshell secundaria en la salida.

Sin embargo, esto no está codificado de manera óptima; En este caso, dos subshells requieren ejecución (el costo de una creación de subshell es muy mínimo, pero si tiene muchas subshells creadas en alta frecuencia, el costo es importante), y el listado directamente se solicita dos veces (generando E/S adicionales ralentizar nuestro código a la velocidad del subsistema de E/S y el tipo de disco utilizado). Vamos a poner esto en una variable:

$ Count = "$ (ls [a -z]* 2>/dev/null | wc -l)"; if [$ count -gt 0]; Entonces echo "encontró exactamente $ Count ocurrencias de archivos [A-Z]*!"; Fi encontró exactamente 2 ocurrencias de archivos [A-Z]*! 

Excelente. Este es un código más óptimo; Se usa una sola subshell y el resultado se almacena en una variable que luego se usa dos veces, y solo es necesaria una sola recuperación de listado de directorio de disco. Tenga en cuenta también que esta solución puede ser más segura de hilo.

Por ejemplo, en el si Declaración que tenía dos subshells, si en el tiempo entre la ejecución de esas subshells se creó un tercer archivo, el resultado puede verse así: Encontró exactamente 3 ocurrencias de archivos [A-Z]*! Mientras que el primero si declaración (usando la primera subshell) realmente calificada en Si 2 -gt 0 - i.mi. 2. Haría poca diferencia en este caso, pero puede ver cómo en alguna codificación puede ser muy importante tener en cuenta.

Ejemplo 2: subshells para el cálculo

$ touch z $ echo $ [$ (fecha + %s) - $ (stat -c %z ./z)] 1 $ Echo $ [$ (fecha + %s) - $ (stat -c %z ./z)] 5 

Aquí creamos un archivo, a saber z, y posteriormente descubrió la edad del archivo en segundos utilizando el segundo comando. Unos segundos después, ejecutamos el comando nuevamente y podemos ver que el archivo ahora tiene 5 segundos de edad.

El fecha +%s El comando nos da el tiempo actual en segundos desde Epoch (1970-01-01 UTC), y stat -c %z nos da los segundos desde la época del archivo que se creó anteriormente, y ahora se hace referencia aquí como ./z, Entonces, todo lo que posteriormente necesitamos hacer es restar a estos dos unos de otros. Colocamos el fecha +%s Primero, ya que este es el número más alto (la hora actual) y, por lo tanto, calcule correctamente el desplazamiento en segundos.

El -C opción para estadística simplemente indica que queremos un formato de salida particular, en este caso %Z, o en otras palabras el tiempo desde la época. Para fecha La sintaxis para la misma idea es +%s, aunque en relación con el tiempo actual y no está relacionado con un archivo en particular.

Ejemplo 3: Subshells Inside SED y otras herramientas

$ echo '0'> a $ sed -i "s | 0 | $ (whoami) |" ./A $ Cat A Roel 


Como puede ver, podemos usar una subshell en casi cualquier comando que ejecutemos en la línea de comando.

En este caso, creamos un archivo a con como contenido 0 y posteriormente en línea reemplazar el 0 a $ (Whoami) que, cuando la subshell se ejecute como el comando se analiza, sustituirá el nombre de usuario pilotear. Tenga cuidado de no usar citas individuales, ya que esto hará la subshell inactiva porque la cadena se interpretará como texto literal:

$ echo '0'> a $ sed -i 's | 0 | $ (whoami) |' ./A $ Cat A $ (Whoami) 

Tenga en cuenta aquí que el sed Sintaxis habilitada (S | 0 |… |) todavía funciona correctamente (!), mientras que la funcionalidad de la subshell de Bash ps No!

Ejemplo 4: Uso de Eval y A For Loop

$ Loops = 3 $ echo 1 ... $ loops 1 ... 3 $ eval echo 1 ... $ loops 1 2 3 $ para i en $ (echo 1 ... $ loops); hacer echo "$ i"; hecho 1 ... 3 $ para i en $ (eval echo 1 ... $ loops); hacer echo "$ i"; hecho 1 2 3 

Este ejemplo, aunque no es la forma óptima de realizar una sencilla para Loop, nos muestra algunas formas de integrar subshells incluso dentro de los bucles. Usamos el evaluación declaración para procesar el 1 ... 3 texto en 1 2 3 que luego se puede usar directamente dentro del para cláusula de repetición de bucle.

A veces, el uso de subshells y el suministro de información en línea en línea a través de subshells no siempre es evidente, y puede requerir algunas pruebas, ajustes y ajuste antes de que las subshells se ejecuten como se esperaba como se esperaba. Esto es normal y mucho en línea con la codificación bash normal.

Conclusión

En este artículo, exploramos algunos ejemplos más profundos y avanzados del uso de subshells en Bash. El poder de las subshells le permitirá transformar la mayoría de los scripts de una línea en versiones mucho más poderosas de los mismos, sin mencionar la posibilidad de usarlos dentro de sus scripts. Cuando comience a explorar subshells y encuentre algunas formas agradables de usarlas, publíquelas a continuación en los comentarios!

Disfrutar!

Tutoriales de Linux relacionados:

  • Cosas para instalar en Ubuntu 20.04
  • Cosas que hacer después de instalar Ubuntu 20.04 fossa focal Linux
  • Subshells de Linux para principiantes con ejemplos
  • Una introducción a la automatización, herramientas y técnicas de Linux
  • Cómo usar subshells Bash dentro de declaraciones
  • Cosas que hacer después de instalar Ubuntu 22.04 Jellyfish de Jammy ..
  • Comandos de Linux: los 20 comandos más importantes que necesitas ..
  • Comandos básicos de Linux
  • Descarga de Linux
  • Instale Arch Linux en VMware Workstation