====== BASH CookBook ====== La idea de esta sección es la de almacenar algunas ideas de cómo hacer cosas en BASH Una fuente inagotable de comandos y recetas BASH es: * http://www.commandlinefu.com/commands/browse ===== Cómo asignar valores a variables con read ===== Es habitual correr comandos que dan 2 o más resultados y queremos asignar estos valores a dos o más variables. Podemos usar el manco **read** del **bash**, pero... **read** pretende leer lineas de texto de un archivo. Si lo que queremos es que lea valores para dos o más variables que provienen de **stdout** de otros comandos o de un pipe, podemos hacerlo con **here files**: read a b <<< $(echo 1 2); echo $a $b Con el uso de ''<<<'' podemos forzar que read lea de stdout y que asigne datos a las variables **a** y **b** en función de lo que devuelva por **stdout** lo que se ejecuta dentro del subshell ''$(...)'' Por ahora es la única manera que encontré de asignar valores obtenidos como resultado de un comando a más de una variable del bash. Porque lo habitual es a=$(echo 1 2) con lo cual la variable ''$a'' toma el valor ''"1 2"'', pero la idea es que "1" vaya a una variable y "2" vaya a otra variable. ===== Generación de números aleatorios ===== * La forma más sencilla es usar la variable $RANDOM, que devuelve números entre 0 y 32767 para más control, si queremos rangos menores, podemos usar la operación módulo, por ej. para un número entre 0 y 99: let R=$RANDOM%100 echo $R para un número entre 1 y 100: let R=$RANDOM%100+1 * Otra forma de generar un número aleatorio entre 1 y 100 consiste en usar la siguiente receta: seq 1 100|shuf|head -1 explicación: seq genera la secuencia, shuf genera una permutación aleatorio y head devuelve el primer número de la lista * Otra receta, usando octal dump: od -vAn -N2 -i < /dev/urandom explicación: con esa sentencia se generan números entre 0 y 65535 * -v: output duplicates * -An: no offset printed (no imprime la posición de los bytes en la salida) * -N2: número de bytes tomados del archivo (en este caso 2, si uso 1 entonces los números son entre 0 y 255) * -i: formato del número: entero sin signo (ver otras opciones en man od) ==== Números Aleatorios en otras Bases (Hexadecimal, binario, octal, etc.) ==== === HEXADECIMAL === $(dd if=/dev/random bs=1 count=1 2>/dev/null | od -An -tx1 | tr -d ' \t\n') od -N32 -x < /dev/urandom | head -n1 | cut -b9- | sed 's/ //gi' openssl rand -hex 16 head -c 6 /dev/urandom | od -x | head -n 1 | sed -e 's/^0* //' -e 's/ //g' cat /dev/urandom | tr -cd 'a-f0-9' | head -c 2 hexdump -n 16 -v -e '/1 "%02X"' /dev/urandom Dígitos hexadecimales: printf "%x" $(($RANDOM%16)) === Cómo generar una MAC aleatoria === Por ejemplo, queremos generar una MAC aleatoria, dada una ID de fabricante determinada: ''00-60-2F-xx-xx-xx'' echo -n 00-60-2F; dd bs=1 count=3 if=/dev/random 2>/dev/null |hexdump -v -e '/1 "-%02X"' o, una manera alternativa de generar ternas de HEX: printf "%02x-%02x-%02x" $(($RANDOM%256)) $(($RANDOM%256)) $(($RANDOM%256)) === Cómo chequear en bash una MAC === [[ $MAC =~ ([a-zA-Z0-9]{1,2}:){5}[a-zA-Z0-9]{2} ]] Esto devuelve ''0'' si ''$MAC'' corresponde a una MAC address y ''1'' en caso contrario ==== Cómo extraer números IPs de un archivo de texto ==== Se puede usar el comando grep que extrae un listado de números IPs: grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' archivo.log ==== Strings y substrings ==== Sea ''var=9357''. Para saber el largo de un string en bash, se puede usar el ''#'': echo ${#var} 4 Si quiero extrar un substring, puedo usar '':'' para especificar la posición de arranque del substring que me interese y luego el largo del substring. ejemplo: echo ${var:2:2} 57 echo ${var:0:1} 9 Recordar que el primer índice es 0 (cero)!!! ==== Remover caracteres no numéricos de un string ==== Desde el propio bash: VAR="Berp.,-1234grok73" Pattern substitution: con ''/'', en el siguiente ejemplo se sustituyen dígitos por nada, es decir que se eliminan los dígitos echo ${VAR//[[:digit:]]/} Berp,.-grok Lo mismo, pero ahora con caracteres alfabéticos echo ${VAR//[[:alpha:]]/} .,-123473 Si queremos eliminar todos los caracteres alfanuméricos: echo ${VAR//[[:alpha:][:digit:]]/} .,- Ejemplo con ''tr'': tr -dc '0-9' <<< "a12.345-&3q4" 1234534 Ejemplo con ''sed'': sed 's/[^0-9]*//g' <<< "a12.345-&3q4" 1234534 ==== Descomponer un string en sus caracteres (o un número en sus dígitos) ==== Sabiendo el largo del string, puedo usar un for loop para descomponerlo var=9357 for (( i=0; i < ${#var}; i++ )); do echo ${var:$i:1}; done 9 3 5 7 Para almacenarlos en un array var=9357 for (( i=0; i < ${#var}; i++ )); do digits[$i]=${var:$i:1}; done echo ${digits[0]} 9 **Ojo**: no dejar espacio entre la variable y el signo de igual para que funcione la asignación en bash. ==== Descomponer un string usando un separador ==== Sea por ejemplo: var="uno:dos:tres:cuatro" Podemos descomponer ese string, usando '':'' como separador, usando el comando ''read'' IFS=':' read -ra array <<< "$var" for i in "${array[@]}"; do echo $i; done uno dos tres cuatro ==== Hacer producto escalar de vectores enteros ==== vec1=(1 2 3 4) vec2=(5 6 7 8) let e=0 for (( i=0; i < ${#vec1[@]}; i++ )); do let e=$e+${vec1[$i]}*${vec2[$i]}; done echo $e 70 **Ojo:** en el for loop hay que usar ''${#vec1[@]}'' para saber el largo del array ''vec1''.