split in bash – cut [ seconda parte ]

Nel precedente post abbiamo visto l’utilizzo canonico di cut: separare i diversi campi delimitati all’interno di una stringa. Potremmo avere a che fare con un altro tipo di file, anch’esso molto comune , che contiene dei record, memorizzati uno per riga, i cui campi non sono delimitati da caratteri speciali ma registrati uno dopo l’altro in base ad una loro lunghezza predefinita. In questi casi è possibile selezionare parti della stringa per offset.

Selezionare per offset significa suddividere la stringa in base ai caratteri che la compongono. Tali caratteri possono essere selezionati analogamente ai campi nel post precedente. C’è una sola differenza: invece di specificare l’indice del campo da selezionare se ne specifica l’offset a partire dal primo carattere della stringa utilizzando il parametro -c al posto di -f.

Esiste anche un parametro -b che permette di fare riferimento ai byte della stringa (-b). Mentre scrivo non c’è differenza tra i due parametri che avranno comportameni diversi con l’internazionalizzazione del sistema operativo e l’introduzione dei caratteri multibyte (ad esempio UTF-16).

Non c’è molto altro da aggiungere, non resta che sperimentare per prendere confidenza con il comando.

E questo è tutto

Split in bash – cut

Spesso e volentieri un amministratore di sistema si trova a dover manipolare record in forma di righe di testo in cui i campi sono fissi o separati da un carattere che fa da separatore.

Che si tratti di un file csv (comma separated values: valori separati da virgola) o del file delle password di un sistema linux cut è il comando che fa per noi.

Si tratta di un programma molto versatile che permette di spezzettare una stringa in più parti secondo diversi criteri che conviene illustrare con alcuni esempi.

Prendiamo ad esempio la stringa “primo:secondo:terzo:quarto:quinto:sesto” e cerchiamo di spezzarla in più parti.

$ echo primo:secondo:terzo:quarto:quinto:sesto | cut -f 3 -d:
terzo
$ echo primo:secondo:terzo:quarto:quinto:sesto | cut -f 3,2 -d:
secondo:terzo
$ echo primo:secondo:terzo:quarto:quinto:sesto | cut -f 2-4 -d:
secondo:terzo:quarto
$

Questi esempi illustrano l’utilizzo del parametro f, che sta per field, ed il parametro d, delimiter.

il parametro -d (o anche –delimiter) indica il carattere che dovrà essere considerato il separatore dei vari campi. In questo caso il delimitatore è rappresentato dai due punti. In caso di spazio o carattere che verrebbe espanso dalla shell bisogna farlo precedere dal backslash; ad esempio per indicare lo spazio come delimitatore si utilizzerebbe la sintassi “-d\ “. Nota: non sono possibili separatori multipli

Il parametro -f invece stabilisce quali campi devono essere riportati come risultato. Ci sono più modalità di selezione:

  • la selezione singola, ad esempio -f 3, è il caso più semplice e prevede che per ogni riga in ingresso venga messo in output una riga che contiene solo il campo specificato (i campi vengono contati a partire da 1);
  • la selezione multipla permette di specificare un intervallo di campi a partire dai suoi estremi, ad esempio -f 3-7 seleziona tutti i campi dal terzo al settimo compresi gli estremi. E’ importante che gli estremi siano ordinati, prima il minore, ma non è necessario che siano tutti presenti, se l’estremo superiore dell’intervallo non esiste verranno selezionati tutti i campi disponibili fino alla fine della stringa;
  • l’ultima modalità di selezione, la sequenza, permette di elencare, separandoli con delle virgole campi o intervalli di campi. L’esempio riportato -f 3,2 serve a far notare che l’ordine dei campi nella selezione è ininfluente e che –f 2,4 e -f 4,2 sono equivalenti e che verranno riportati in output i campi 2 e 4 (in quest’ordine). Altri esempi validi sono: -f 3-5,1 o -f 1,1-3,9-11. Nota: un errore comune nella selezione multipla consiste nel far seguire la virgola da uno spazio come si dovrebbe fare secondo le regole di dattilografia;

Non abbiamo finito di sviscerare le potenzialità di cut ma penso che potremmo fermarci qui in attesa di un prossimo post in cui tratteremo della selezione per offset

E questo e tutto (fino al prossimo post)

Split di una stringa in bash

Direi che ormai è arrivato il momento di un articolo che abbia una certa utilità (e quindi si merita la lettera iniziale maiuscola :))

Normalmente preferisco usare cut o awk per separare i diversi token contenuti in una stringa.

Stamattina devo sostituire alcune regole di accesso su un firewall (iptables), ho bisogno di individuarle con delle regole ad hoc contenute in un array, la prima riga individua le regole e crea una lista con le loro posizioni.

NEWRULE[1]='iptables -R %s -i eth0 -t tcp --dport 443 --jump HTTPS_ENABLED'
NEWRULE[2]='iptables -R %s -i eth2 -t tcp --dport 443 --jump HTTPS_ENABLED'
 RULES_POSITION=`$IPT -vn --line-number -L INPUT | grep 443 | grep -n . | cut -f1 -d\ `
for INPOINT in $RULES_POSITION; do
   INDICE=${INPOINT%:*}
   POSITION=${INPOINT#*:}
   printf "${NEWRULE[INDICE]}" $POSITION
done


tra il codice riportato ci interessano in particolare le righe

   INDICE=${INPOINT%:*}
   POSITION=${INPOINT#*:}

ci aspettiamo in input delle stringhe del tipo formate da due numeri separate dai due punti, ad esempio 1:24.

Nel nostro caso il separatore è il simbolo di due punti

L’espansione si attiva con ${}, all’interno delle parentesi graffe va inserito il nome della variabile da separare in due. %:* prende la parte della variabile che va dall’inizio alla prima occorrenza del separatore (in questo caso :). Una nota. Questo comportamento è detto lazy , se si vuole utilizzare una selezione greedy bisogna usare un doppio simbolo di percentuale.

Cercherò di spiegarmi meglio:

  • La selezione greedy (=avida) va a cercare il separatore più lontano dall’inizio della stringa
  • La selezione lazy (=svogliata) invece si ferma non appena trova il primo separatore utile

Il comportamento è analogo per l’operatore # (## in versione greedy) che invece seleziona a partire dall’ultimo carattere della string.