Faq Bash

Faq bash

Pubblicato il Pubblicato in Faq, Faq bash
See the article in English

Rinominare un gruppo di file in base ad una regexpr

Supponiamo di voler rinominare il nome di un gruppo di file che hanno il seguente template:

file1_tmp.sh
file2_tmp.sh
...
file99_tmp.sh

e supponiamo di voler togliere la parte centrale ‘_tmp’ in tutti i file. Possiamo utilizzare il comando “rename” o “prename”:

 rename 's/_tmp//' *.sh

 

Vedi tutte le FAQs

Redirigere lo standard error sullo standart output

Per redirigere lo standard error di un comando in shell basta utilizzare la seguente sinstassi seguente:

ls file_non_esistente 2>&1 | grep File

oppure ancor meglio per non avere sul terminale lo standard error basta buttarlo in /dev/null

ls file_non_esistente 2>/dev/null

Gli identificativi standard o canali standard (o standard streams) aperti automaticamente sono:

  • 0 standard input
  • 1 standard output
  • 2 standard error

 

Vedi tutte le FAQs

Uso di array semplici in bash

Con Bash per dichiarare esplicitamente un array bisogna utilizzare

declare -A mioarray

Per avere il valore dell’elemento 5 basta scrivere

echo $[mioarray[5]

mentre per cambiare il valore  bisogna scrivere

mioarray[5]='nuovo valore'

${mioarray[*]} o ${mioarray[@]} viene espanso da tutti i valori dell’array mentre $[#mionome[@]} viene espanso con la lunghezza dell’array

Cosa possiamo fare con gli array? Ad esempio memorizzare l’output di un comando di cui ogni riga vorremmo che vada su un elemento differente.

IFS=$'\n' mioarray=($(ls -alh))

A questo punto possiamo stampare l’output come

 IFS=$'\n' echo "${mioarray[*]}"

Attenzione: i doppi apici sono importanti per non avere l’output su un’unica riga.

Facendo così potremmo fare diversi test sullo stesso output catturato una sola volta.

 

 

Vedi tutte le FAQs

Uso di array associativi in bash

Per dichiarare un array associativo bisogna dichiararlo con

declare -A mioarray/

e come indice si può utilizzare una stringa, questo significa che

mioarray[test]='aa'
echo ${mioarray[test]} # restituisce 'aa'

 

Vedi tutte le FAQs

Convertire da Bash un numero decimale in binario

Supponiamo di star lavorando su uno script bash e che per qualche esigenza, nemmeno troppo difficile dalla realtà, sia indispensabile dover convertire un numero o una variabile decimale in numero binario.

Ci sono naturalmente diverse soluzioni ma quella che vi propongo non fa utilizzo di programmi esterni ma è bash a tutti gli effetti.

Per prima cosa dobbiamo sapere il valore massimo del numero binario da ottenere in Bash ovvero in quanti bit potrà essere compreso.

Consideriamo che stiamo parlando di un byte e quindi 8 bit e cioè il numero binario andrà da 00000000 a 11111111 (da 0 a 255) allora possiamo scrivere:

bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
echo ${bin[*]}
come convertire un numero decimale in binario con bash
bash – array di numeri binari

Il più è fatto, infatti per avere il risultato ad esempio del numero 125 o di 78 in binario basta semplicemente

echo ${bin[125]}
01111101
echo ${bin[78]}
01001110

Se cambia il range del numero binario ad esempio se raddoppiamo o quadruplichiamo basta che definiamo la variabile bin con uno o due blocchi in più del tipo {0..1}.

Quindi riassumendo, la variabile bin dovrà contenere tanti blocchi {0..1} in base al numero massimo binario che si vuole ottenere cioè se il massimo numero è 2n -1 allora ci vorranno n gruppi {0..1}.

Come esempio se n=10 e quindi 210 -1=1023 i blocchi saranno 10

bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
echo ${bin[1023]}
1111111111
Vedi tutte le FAQs

Convertire da Bash un numero decimale in esadecimale

Come per la faq con la conversione in binario anche in questa facciamo utilizzo delle fantastiche estensioni bash sulle parentisi graffe per convertire in esadecimale.

Quindi, considerando sempre la faq bash sul binario partiamo inizialmente con il convertire un numero decimale tra 0 e 255 che corrisponde ad una cifra esadecimale tra 0 ed FF:

hex=({{0..9},{a..f}}{{0..9},{a..f}})
echo ${hex[*]}
come convertire un numero decimale in esadecimale con bash
bash- array di numeri esadecimali

A questo punto per avere il risultato del numero 200 oppure di 21 basta

echo ${hex[200]}
c8
echo ${hex[21]}
15

Se cambia il range del numero esadecimale ad esempio se raddoppiamo o quadruplichiamo basta che definiamo la variabile hex con uno o due blocchi in più del tipo {0..9},{a..f}.

Quindi riassumendo, la variabile hex dovrà contenere tanti blocchi {0..9},{a..f} in base al numero massimo binario che si vuole ottenere cioè se il massimo numero è 16n -1 allora ci vorranno n gruppi {0..9},{a..f}.

Come esempio se n=4 e quindi 164 -1=65535 i blocchi saranno 4

hex=({{0..9},{a..f}}{{0..9},{a..f}}{{0..9},{a..f}}{{0..9},{a..f}})
echo ${hex[60000]}
ea60
echo ${hex[37]}
0025
Vedi tutte le FAQs

Come convertire una netmask IPV4 in CIDR

Per passare da una netmask IPV4 a l’equivalente CIDR potrebbe venir in mente di fare la cosa più semplice ovvero utilizzare un blocco case o degli if annidati per ottenere il CIDR equivalente tanto i netmask o CIDR disponibili sono solo 32 e cioè

NetmaskAddress/CIDRAdresses
255.255.255.255a.b.c.d/3220
255.255.255.254a.b.c.d/3120
255.255.255.252a.b.c.d/3021
255.255.255.248a.b.c.d/2922
255.255.255.240a.b.c.d/2823
255.255.255.224a.b.c.d/2724
255.255.255.192a.b.c.d/2625
255.255.255.128a.b.c.d/2526
255.255.255.0a.b.c.0/2427
255.255.254.0a.b.c.0/2328
255.255.252.0a.b.c.0/2229
255.255.248.0a.b.c.0/21210
255.255.240.0a.b.c.0/20212
255.255.224.0a.b.c.0/19213
255.255.192.0a.b.c.0/18214
255.255.128.0a.b.c.0/17215
255.255.0.0a.b.0.0/16216
255.254.0.0a.b.0.0/15217
255.252.0.0a.b.0.0/14218
255.248.0.0a.b.0.0/13219
255.240.0.0a.b.0.0/12220
255.224.0.0a.b.0.0/11221
255.192.0.0a.b.0.0/10222
255.128.0.0a.b.0.0/9223
255.0.0.0a.0.0.0/8224
254.0.0.0a.0.0.0/7225
252.0.0.0a.0.0.0/6226
248.0.0.0a.0.0.0/5227
240.0.0.0a.0.0.0/4228
224.0.0.0a.0.0.0/3229
192.0.0.0a.0.0.0/2230
128.0.0.0a.0.0.0/1231
0.0.0.00.0.0.0/0232
Netmask to CIDR

Se vogliamo, invece, realizzare una funzione che converta il netmask in CIDR abbiamo bisogno di sapere come convertire un numero decimale in binario come prima cosa.

fromNetmaskToCidr() {
  local netmask=$1
  local bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
  local b=''
  local n
  local cidr
  for n in ${netmask//./ }; do
    if [ $n -gt 255 ]; then
      echo -e "\t[ERROR] netmask $netmask format error in '.$n'. I will use .255 insted of .$n"
      n=255
    fi
    if [ $n -ne 0 -a $n -ne 128 -a $n -ne 192 -a $n -ne 224 -a $n -ne 240 -a $n -ne 248 -a $n -ne 252 -a $n -ne 254 -a $n -ne 255 ]; then
      echo -e "\t[ERROR] netmask $netmask format error in '.$n' (it must be 0,128,192,224,240,248,252,254,255). I will use .255 insted of .$n"
      n=255
    fi
    # $b is the binary of $netmask
    b=${b}${bin[$n]}
  done
  # remove right "0" bits from $b
  b=${b/%0*}
  cidr=${#b}
  echo $cidr
}

Quel che si fa è convertire i 4 ottetti del netmask in binario e metterli in serie nell’unica variabile “b” quindi rimuovere i bit a 0 presenti nella destra del numero binario complessivo.
Infine basta contare il numero dei bit rimasti per avere il CIDR che poi verrà restituito in uscita.

Riferimenti

Vedi tutte le FAQs

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *