MIT2020 cram school- (2) Herramientas y scripts de Shell

Script de Shell

Para asignar una variable en bash, use la foo=barsintaxis y use $fooel valor de la variable de acceso. Tenga en cuenta que foo = barno funciona, ya que se interpreta como llamar al programa foo con los parámetros = y bar. En términos generales, en un script de shell, el carácter de espacio dividirá los parámetros de ejecución , y puede ser confuso al principio, por lo tanto, siempre marque esta opción.

Las cadenas en bash se pueden definir con 'y delimitadores, pero no son equivalentes. La 'cadena delimitada es una cadena de texto, y el valor de la variable no se reemplazará, pero la cadena delimitada sí.

foo=bar
echo "$foo"
# prints bar
echo '$foo'
# prints $foo

Al igual que con la mayoría de los lenguajes de programación, soportes de bash fluyen tecnología de control , incluyendo if, case, whiley for. Del mismo modo, bash tiene funciones que aceptan parámetros y pueden manipularlos. El siguiente es un ejemplo de una función que crea un directorio y un CD en él.

mcd () {
    mkdir -p "$1"
    cd "$1"
}

Aquí $1está el primer parámetro del script / función. A diferencia de otros lenguajes de script, bash usa varias variables especiales para referirse a parámetros, códigos de error y otras variables relacionadas.

$0-El nombre del guión

$1A los $9parámetros de la secuencia de comandos. $ 1 es el primer parámetro y así sucesivamente.

$@-Todos los parámetros

$#-El número de parámetros

$? -El código de retorno del comando anterior

$$-Número de identificación del proceso del script actual

!!-El último comando completo, incluidos los parámetros. Un patrón común es ejecutar solo un comando que falla debido a la falta de permisos, y luego puede sudo!!ejecutarlo rápidamente usando sudo

$_-El último parámetro del último comando. Si está en un shell interactivo, también puede obtener este valor rápidamente escribiendo Escy siguiendo ..

Comando por lo general STDOUTproduce una salido, por STDERRdevolución de error de código de retorno de error de una manera más amigable guiones informen de errores. El código de retorno o el estado de salida es cómo el script / comando debe comunicar cómo se ejecuta. Un valor de 0 generalmente indica que todo es normal, y un valor diferente de 0 indica que se ha producido un error.

Los códigos de salida se pueden usar para ejecutar comandos condicionalmente usando &&(y operadores) y ||(u operadores). Los comandos también se pueden ;separar en la misma línea con punto y coma . trueEl programa siempre tendrá un código de retorno 0 y el falsecomando siempre tendrá un código de retorno 1. Veamos algunos ejemplos.

false || echo "Oops, fail"
# Oops, fail

true || echo "Will not be printed"
#

true && echo "Things went well"
# Things went well

false && echo "Will not be printed"
#

false ; echo "This will always run"
# This will always run

Otro patrón común es esperar la salida de un comando como una variable. Esto se puede hacer mediante la sustitución de comandos. Cada vez que lo coloque $(CMD), se ejecutará CMD, tomará la salida del comando y lo reemplazará en su lugar. Por ejemplo, si $(ls)realiza esta operación en un archivo, primero se llamará al shell lsy luego iterará en estos valores. Una característica similar poco conocida es el reemplazo de procesos, <(CMD)que ejecuta CMD y coloca el resultado en un archivo temporal y lo reemplaza con el nombre del archivo <(). Esto es útil cuando el valor esperado del comando se pasa por archivo en lugar de STDIN. Por ejemplo, diff<(ls foo)<(ls bar)la pantalla fooy barlas diferencias entre los archivos.

Debido a que este es un gran volcado de información, veamos un ejemplo que demuestra estas características. Atravesará el parámetro que proporcionamos, la cadena foobar, grepy si no se puede encontrar, añádalo al archivo como comentario.

#!/bin/bash

echo "Starting program at $(date)" # Date will be substituted

echo "Running program $0 with $# arguments with pid $$"

for file in $@; do
    grep foobar $file > /dev/null 2> /dev/null
    # When pattern is not found, grep has exit status 1
    # We redirect STDOUT and STDERR to a null register since we do not care about them
    if [[ $? -ne 0 ]]; then
        echo "File $file does not have any foobar, adding one"
        echo "# foobar" >> "$file"
    fi
done

En la comparación, probamos $?si no es igual a 0. Bash implementa muchas de estas comparaciones. Al realizar comparaciones en Bash, puede encontrar una lista detallada en la página del manual. Intente usar corchetes dobles en [[]]lugar de corchetes simples [].

Al iniciar un script, generalmente debe proporcionar parámetros similares. Bash puede simplificar este proceso realizando la expansión del nombre de archivo y expandiendo las expresiones. Estas técnicas se conocen comúnmente como bolas de concha.

Comodines: siempre que desee realizar algún tipo de coincidencia de comodines, puede usar y *combinar uno o cualquier número de caracteres respectivamente. Por ejemplo, un archivo determinado foo, foo1, foo2, foo10y bar, el comando rm foo?será borrado foo1y foo2, mientras que rm foo*la adición borrar bartodo el contenido fuera.

Llaves: {}siempre que haya una subcadena común en una serie de comandos, puede usar llaves de bash para expandirla automáticamente. Esto es muy conveniente al mover o convertir archivos.

convert image.{png,jpg}
# Will expand to
convert image.png image.jpg

cp /path/to/project/{foo,bar,baz}.sh /newpath
# Will expand to
cp /path/to/project/foo.sh /path/to/project/bar.sh /path/to/project/baz.sh /newpath

# Globbing techniques can also be combined
mv *{.py,.sh} folder
# Will move all *.py and *.sh files


mkdir foo bar
# This creates files foo/a, foo/b, ... foo/j, bar/a, bar/b, ... bar/j
touch {foo,bar}/{a..j}
touch foo/x bar/y
# Show differences between files in foo and bar
diff <(ls foo) <(ls bar)
# Outputs
# < x
# ---
# > y

Inserte la descripción de la imagen aquí

Tenga en cuenta que no es necesario escribir un script con bash para llamar desde el terminal. Por ejemplo, aquí hay un script simple de Python que genera parámetros en orden inverso

#!/usr/local/bin/python
import sys
for arg in reversed(sys.argv[1:]):
    print(arg)

El shell sabe usar el intérprete de Python en lugar de los comandos del shell para ejecutar este script porque incluimos una línea shebang en la parte superior del script. Es envuna buena práctica escribir una línea shebang con un comando. El comando se analizará en cualquier ubicación del sistema donde se encuentre el comando, mejorando así la portabilidad del script. Para resolver el problema de ubicación, envutilizaremos las PATHvariables de entorno que presentamos en la primera lección . En este ejemplo, se ve la línea shebang #!/usr/bin/env python.

Deben recordarse algunas diferencias entre las funciones de shell y los scripts:

  • La función debe usar el mismo idioma que el shell, y el script se puede escribir en cualquier idioma. Es por eso que shebang que contiene scripts es importante.

  • La función se carga una vez al leer su definición. Se cargan cada vez que se ejecuta el script. Esto hace que las funciones de carga sean un poco más rápidas, pero cada vez que las cambie, debe volver a cargar sus definiciones.

  • La función se ejecuta en el entorno de shell actual y el script se ejecuta en su propio proceso. Por lo tanto, las funciones pueden modificar variables de entorno, por ejemplo, cambiar el directorio actual, mientras que los scripts no pueden. El script pasará la variable de entorno de valor exportada usando export

  • Como cualquier lenguaje de programación, las funciones son una construcción poderosa para la modularidad, la reutilización de código y la claridad del código de shell. Por lo general, los scripts de shell contendrán sus propias definiciones de funciones.

Herramientas de Shell

Descubre cómo usar los comandos

En este punto, es posible que desee saber cómo encontrar el indicador del comando en la sección de alias (como ls -l, mv -iy mkdir -p). De manera más general, con un comando, ¿cómo puede saber qué hace y sus diferentes opciones?

Como vimos en el curso de shell, el primer método es usar el indicador -ho --helppara llamar al comando. Un método más detallado es usar mancomandos. manEs la abreviatura de manual, que proporciona una página de manual (llamada página de manual) para el comando que especifique. Por ejemplo, se man rmmostrará rmel comportamiento del comando y los indicadores que utiliza, incluidos los -iindicadores que se muestran anteriormente . Incluso si instala un comando no nativo, si el desarrollador escribe una entrada de página de manual y la incluye como parte del proceso de instalación, también habrá una entrada de página de manual. Para las herramientas interactivas (como las herramientas basadas en ncurses), generalmente puede usar :helpcomandos o escribir en el programa .

A veces, las páginas de manual pueden ser descripciones demasiado detalladas de los comandos, y es difícil descifrar los signos / sintaxis utilizados para casos de uso comunes. La página TLDR es una buena solución complementaria, que se centra en los casos de uso de ejemplo que dan comandos para que pueda encontrar rápidamente las opciones que desea utilizar.

Encuentra archivos

Una de las tareas repetitivas más comunes que enfrenta cada programador es encontrar archivos o directorios. Viene con todos los sistemas similares a UNIX find, esta es una buena herramienta de shell para encontrar archivos. findLos archivos que cumplan ciertas condiciones se buscarán de forma recursiva. Algunos ejemplos:

# Find all directories named src
find . -name src -type d
# Find all python files that have a folder named test in their path
find . -path '**/test/**/*.py' -type f
# Find all files modified in the last day
find . -mtime -1
# Find all zip files with size in range 500k to 10M
find . -size +500k -size -10M -name '*.tar.gz'

Además de enumerar archivos, findtambién puede realizar operaciones en archivos que coinciden con la consulta. Esta propiedad es muy útil para simplificar tareas que pueden ser bastante monótonas.

# Delete all files with .tmp extension
find . -name '*.tmp' -exec rm {} \;
# Find all PNG files and convert them to JPG
find . -name '*.png' -exec convert {} {.}.jpg \;

Aunque findomnipresente, su gramática a veces es difícil de recordar. Por ejemplo, para encontrar simplemente un archivo que coincida con un patrón, debe realizarlo find -name '*PATTERN*'(si desea que la coincidencia de patrones no distinga entre mayúsculas y minúsculas, ejecútelo -iname). Puede comenzar a crear alias para estas escenas, pero como parte de la filosofía de shell, es bueno explorar utilizando métodos alternativos. Recuerde, una de las mejores características del shell es que puede encontrar (o incluso escribir sus propios) reemplazos para ciertos programas simplemente llamando al programa. Por ejemplo, fdes un método de búsqueda simple, rápido y fácil de usar. Proporciona una buena configuración predeterminada, como salida de color, coincidencia de expresión regular predeterminada, compatibilidad con Unicode, y me parece una sintaxis más intuitiva. PATTERNLa sintaxis del modo de búsqueda es fd PATTERN.

La mayoría de las personas están de acuerdo findy fdson muy buenos, pero algunas personas pueden querer saber que cada vez que una eficiencia de búsqueda de archivos, en lugar de compilado algún índice o base de datos para la búsqueda rápida. Este es locateel propósito. locateUse la updatedbbase de datos actualizada. En la mayoría de los sistemas, updatedba través de cronlas actualizaciones diarias. Por lo tanto, una compensación entre los dos es velocidad y frescura. Además, findy herramientas similares también pueden usar el tamaño del archivo, el tiempo de modificación o los permisos del archivo y otros atributos para encontrar el archivo, y locatesolo usar el nombre.

Encontrar código

Es útil para encontrar archivos, pero generalmente es para encontrar el contenido de los archivos. Un escenario común es buscar todos los archivos que contienen un cierto patrón y la ubicación del patrón en estos archivos. Para lograr esto, la mayoría de los sistemas tipo UNIX proporcionan una grepherramienta de propósito general para hacer coincidir patrones del texto de entrada.

grepHay muchos signos que lo convierten en una herramienta muy versátil. A menudo uso -Cpara obtener el contexto alrededor de la línea coincidente, uso -vpara invertir la coincidencia, es decir, imprimir todas las líneas que no coinciden con el patrón . Por ejemplo, grep -C 5se imprimirán 5 líneas antes y después del partido. Cuando se trata de analizar rápidamente muchos archivos, debe usarlo -Rporque entrará recursivamente en el directorio y encontrará archivos de texto que coinciden con la cadena.

Pero se grep -Rpuede mejorar de muchas maneras, como ignorar .gitcarpetas, usar soporte para múltiples CPU, etc. Por lo tanto, no hay escasez de alternativas desarrolladas, incluyendo ack, ag y rg. Son geniales, pero básicamente satisfacen las mismas necesidades. Ahora insisto en usar ripgrep( rg), considerando su velocidad e intuición. Algunos ejemplos:

# Find all python files where I used the requests library
rg -t py 'import requests'
# Find all files (including hidden files) without a shebang line
rg -u --files-without-match "^#!"
# Find all matches of foo and print the following 5 lines
rg foo -A 5
# Print statistics of matches (# of matched lines and files )
rg --stats PATTERN

Tenga en cuenta que, como con find/ fd, es importante que sepa que puede usar una de estas herramientas para resolver rápidamente estos problemas, mientras que la herramienta específica que usa es menos importante.

Encuentra comandos de shell

Hasta ahora, hemos aprendido cómo encontrar archivos y códigos, pero a medida que comience a pasar más tiempo en el shell, es posible que desee encontrar un comando específico que escriba en algún momento. Lo primero que debe saber es que la flecha hacia arriba volverá al comando anterior; si lo sigue presionando, examinará lentamente su historial de shell.

historyEl comando le permitirá acceder al historial de shell mediante programación. Imprimirá su historial de shell a la salida estándar. Si queremos buscar allí, podemos enviar la canalización de salida grepy buscar patrones. Se history | grep findimprimirá el findcomando con la subcadena " ".

En la mayoría de los shells, puede usar Ctrl+Rpara realizar una búsqueda hacia atrás en el historial . Después de presionar Ctrl+R, puede escribir la subcadena para que coincida con los comandos en el historial. A medida que lo sigas presionando, recorrerás tu entrada histórica. Esto también se puede habilitar con las flechas arriba / abajo en zsh. Además Ctrl+R, hay una buena adición, que es usar fzf vinculante. fzf es un buscador difuso de uso general que se puede usar con muchos comandos.

Auto-señales basadas en la historia history-based autosuggestions. Esta característica fue introducida por primera vez por el shell de peces. Utiliza el último comando que escribe para completar dinámicamente el comando de shell actual automáticamente. Este comando comparte un prefijo común con el comando de shell actual.

Finalmente, una cosa para recordar es que si inicia un comando con un espacio inicial, no se agregará al historial del shell. Esto es muy útil cuando utiliza contraseñas u otra información confidencial para ingresar comandos. Si comete el error de no agregar espacios iniciales, puede eliminar manualmente la entrada editando .bashúhistoryo .zhistory.

Navegación de directorio

Hasta ahora, hemos asumido que ya está en el lugar donde necesita realizar estas operaciones, pero ¿cómo navegar rápidamente por el directorio? Hay muchas formas simples de hacer esto, como escribir alias de shell y crear enlaces simbólicos con ln-s, pero el hecho es que los desarrolladores ahora han encontrado soluciones bastante inteligentes y complejas.

Al igual que con el tema de este curso, generalmente desea optimizar para situaciones comunes. La búsqueda de archivos y directorios utilizados con frecuencia y / o recientemente se puede ordenar por frecuencia (es decir, frecuencia y frecuencia de uso reciente) por herramientas como fasd fasd. El uso más directo es el salto automático, que agrega un comando z que puede usar subcadenas del directorio anterior para crear un cd rápidamente. E. g. Si a menudo va a / home / user / files / cool_project, simplemente puede saltar allí.

Existen herramientas más sofisticadas para obtener rápidamente una visión general de los árboles de estructura de directorios, BROOT o incluso administradores de archivos maduros (como NNN o Ranger-Rever).

Publicado 28 artículos originales · ganado elogios 2 · Vistas 3259

Supongo que te gusta

Origin blog.csdn.net/Maestro_T/article/details/104325031
Recomendado
Clasificación