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:
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
.