Linux Tutorial – Puntata 26

di jolek78

Care/i fruitrici e fruitori del blog, in questi post – ogni domenica mattina – si parlerà del sistema operativo GNU/Linux e degli strumenti per utilizzarlo al massimo delle potenzialità. Cercheremo di spiegare come funziona, cosa è il kernel, come costruirsi una vpn, come settare un firewall e giocare col terminale, usare adb e altro. Se il capitalismo della sorveglianza ci vuole passivi consumatori-consumatrici di servizi noi si risponde con un po’ di “cultura informatica” e un MARAMEO (quasi affettuoso). Buona lettura!

Due notti fa mentre rovistavo fra scatoli e scatoloni alla ricerca di un adattatore slimport  usb-hdmi, ho ritrovato, in un piccolo anfratto impolverato, un vecchio router con openwrt installato, ancora attivo e ancora funzionante. Openwrt, per la cronaca, è una piattaforma opensource basata su linux, molto flessibile, e progettata espressamente per router. Data di produzione: circa quindici anni fa. Diamine, ma da quanto tempo vedo sui miei schermi comandi, terminali e pinguini? Molto, forse troppo. Sia come sia, questo mia ha ricordato che il primo incontro con il comando che vedremo in questo tutorial, awk, fu davvero tanti anni fa quando volevo fare vedere a un amico come si poteva esportare una sola colonna di excel in un semplice file di testo. awk in realtà, più che un comando, è un linguaggio di scripting, e quindi per parlarne, bisognerebbe entrare molto nei dettagli. In questa puntata pero’, come nostro solito, ci terremo sui fondamentali. È domenica, non voglio farvi venire il mal di testa. Bentornati!

– man

 bottega@bottegadelbarbieri  ~  man awk |head -n 18
MAWK(1)                                                                                                      USER COMMANDS                                                                                                      MAWK(1)

NAME
       mawk - pattern scanning and text processing language

SYNOPSIS
       mawk [-W option] [-F value] [-v var=value] [--] 'program text' [file ...]
       mawk [-W option] [-F value] [-v var=value] [-f program-file] [--] [file ...]

DESCRIPTION
       mawk  is  an  interpreter for the AWK Programming Language.  The AWK language is useful for manipulation of data files, text retrieval and processing, and for prototyping and experimenting with algorithms.  mawk is a new awk
       meaning it implements the AWK language as defined in Aho, Kernighan and Weinberger, The AWK Programming Language, Addison-Wesley Publishing, 1988 (hereafter referred to as the AWK book.)  mawk conforms to  the  POSIX  1003.2
       (draft 11.3) definition of the AWK language which contains a few features not described in the AWK book, and mawk provides a small number of extensions.

       An  AWK  program is a sequence of pattern {action} pairs and function definitions.  Short programs are entered on the command line usually enclosed in ' ' to avoid shell interpretation.  Longer programs can be read in from a
       file with the -f option.  Data  input is read from the list of files on the command line or from standard input when the list is empty.  The input is broken into records as determined by the record  separator  variable,  RS.
       Initially, RS = “\n” and records are synonymous with lines.  Each record is compared against each pattern and if it matches, the program text for {action} is executed.

Per questo tutorial utilizzeremo due esempi. Il primo è un file che abbiamo conosciuto nelle prime puntate del tutorial, ed è il /etc/passwd, ovvero dove sono conservate, in maniera criptata, tutte la password e le informazioni appartenenti agli utenti del sistema. Il secondo e’ ovviamente la arcinota novella di Coleridge “the rhyme of the ancient mariner” che abbiamo stra utilizzato in queste ultime puntate. Un giorno Coleridge ci citerà per danni, ne son convinto…

bottega@bottegadelbarbieri  ~  cat the-rhyme-of-the-ancient-mariner.txt |head -n 20 
PART THE FIRST.

It is an ancient Mariner,
And he stoppeth one of three.
"By thy long grey beard and glittering eye,
Now wherefore stopp'st thou me?

"The Bridegroom's doors are opened wide,
And I am next of kin;
The guests are met, the feast is set:
May'st hear the merry din."

He holds him with his skinny hand,
"There was a ship," quoth he.
"Hold off! unhand me, grey-beard loon!"
Eftsoons his hand dropt he.

He holds him with his glittering eye--
The Wedding-Guest stood still,
And listens like a three years child:
     
bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin

– select colum || $
Dunque, partiamo dalla novella di Coleridge e proviamo a selezionare la prima colonna a sinistra. Il gioco e’ inserire il numero della colonna dopo il simbolo del dollaro $. Non è chiaro? Vediamo cosa intendo.

bottega@bottegadelbarbieri  ~  cat the-rhyme-of-the-ancient-mariner.txt |head -n 20 |awk '{print $1}'
PART

It
And
"By
Now

"The
And
The
May'st

He
"There
"Hold
Eftsoons

He
The
And

Cosa succede se proviamo a fare la stessa operazione su /etc/passwd?

bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 |awk '{print $1}'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd
systemd-resolve:x:101:103:systemd

Cosa è successo? Banalmente fra la prima e la seconda colonna non c’era una separazione delimitata da uno spazio, ma da un simbolo, il :. Dunque aggiungiamo fra awk e le parentesi graffe un simbolo:

bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 |awk -F: '{print $1}'
root
daemon
bin
sys
sync
games
man
lp
mail
news
uucp
proxy
www-data
backup
list
irc
gnats
nobody
systemd-network
systemd-resolve

– modify word || $n=word
Ora invece proviamo a modificare, a schermo, la prima parola che ci viene visualizzata sulla prima, sulla seconda e sulla terza colonna col simbolo =. In questo modo introdurremo un altro parametro: con awk possiamo visualizzare più colonne allo stesso momento separate dal simbolo , :

bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 |awk -F: '{print $1="pippo", $2="pluto", $3="paperino"}' 
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino
pippo pluto paperino

Ma com’era l’originale?

bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 |awk -F: '{print $1, $2, $3}' 
root x 0
daemon x 1
bin x 2
sys x 3
sync x 4
games x 5
man x 6
lp x 7
mail x 8
news x 9
uucp x 10
proxy x 13
www-data x 33
backup x 34
list x 38
irc x 39
gnats x 41
nobody x 65534
systemd-network x 100
systemd-resolve x 101

Ok, dobbiamo aggiungere alla lista delle citazioni per danni anche Walt Disney. Ma non è colpa mia se in campo informatico si usano questi nomi fin dall’eta’ della pietra…

– quoting || q=’x’
Vediamo ora cosa succede se vogliamo aggiungere un simbolo all’inizio e alla fine di ogni parola apparenterete a una determinata colonna. Tipicamente, il simbolo sarà ma, per mostrare che la definizione è la stessa, utilizzeremo il simbolo ^ definito dalla variabile q:

bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 |awk -F: '{print q $1 q, q $2 q, q $3 q}' q='^' 
^root^ ^x^ ^0^
^daemon^ ^x^ ^1^
^bin^ ^x^ ^2^
^sys^ ^x^ ^3^
^sync^ ^x^ ^4^
^games^ ^x^ ^5^
^man^ ^x^ ^6^
^lp^ ^x^ ^7^
^mail^ ^x^ ^8^
^news^ ^x^ ^9^
^uucp^ ^x^ ^10^
^proxy^ ^x^ ^13^
^www-data^ ^x^ ^33^
^backup^ ^x^ ^34^
^list^ ^x^ ^38^
^irc^ ^x^ ^39^
^gnats^ ^x^ ^41^
^nobody^ ^x^ ^65534^
^systemd-network^ ^x^ ^100^
^systemd-resolve^ ^x^ ^101^

Se invece definiamo la variabile in un altro modo, ecco cosa succede:

bottega@bottegadelbarbieri  ~  cat /etc/passwd |head -n 20 |awk -F: '{print q $1 d, q $2 d, q $3 d}' q='{' d='}'
{root} {x} {0}
{daemon} {x} {1}
{bin} {x} {2}
{sys} {x} {3}
{sync} {x} {4}
{games} {x} {5}
{man} {x} {6}
{lp} {x} {7}
{mail} {x} {8}
{news} {x} {9}
{uucp} {x} {10}
{proxy} {x} {13}
{www-data} {x} {33}
{backup} {x} {34}
{list} {x} {38}
{irc} {x} {39}
{gnats} {x} {41}
{nobody} {x} {65534}
{systemd-network} {x} {100}
{systemd-resolve} {x} {101}

Chiaro? Nel primo esempio abbiamo definito una sola variabile q prima e dopo la parola. Nel secondo esempio abbiamo definito due variabili differenti, q e d, prima e dopo la colonna. Straordinario vero? Ora che avete capito come funziona, e sapete dalle precedenti puntate che per esportare un file in un altro file possiamo utilizzare il simbolo >, o per aggiungere linee il simbolo >>, avrete sicuramente già capito che questo è uno dei metodi per creare contenuti all’interno di uno script in bash.

– split || ‘/../’
Torniamo ora alla novella di Coleridge. Come sappiamo e’ divisa in sette capitoli separati, nel nostro file, dalla parola “PART”

 bottega@bottegadelbarbieri  ~  cat the-rhyme-of-the-ancient-mariner.txt |grep PART
PART THE FIRST.
PART THE SECOND.
PART THE THIRD.
PART THE FOURTH.
PART THE FIFTH.
PART THE SIXTH.
PART THE SEVENTH.

Facciamo la stessa operazione con awk:

bottega@bottegadelbarbieri  ~  cat the-rhyme-of-the-ancient-mariner.txt |awk '/^PART/ {print $0}' 
PART THE FIRST.
PART THE SECOND.
PART THE THIRD.
PART THE FOURTH.
PART THE FIFTH.
PART THE SIXTH.
PART THE SEVENTH.

Facendo in questo modo si capirà meglio l’operazione che andremo a fare in seguito. In sostanza prima di {print} abbiamo banalmente fatto precedere la parola che volevamo selezionare nel nostro output delimitata fra due simboli /. Ma ora faremo qualcosa di diverso. Occhio:

bottega@bottegadelbarbieri  ~  awk '/PART/{n++}{print > "the-rhyme" n ".txt"}' the-rhyme-of-the-ancient-mariner.txt 
 bottega@bottegadelbarbieri  ~  ls -lha the-rhyme{1..7}.txt
-rw-rw-r-- 1 bottega bottega 3.1K Sep  4 18:36 the-rhyme1.txt
-rw-rw-r-- 1 bottega bottega 2.2K Sep  4 18:36 the-rhyme2.txt
-rw-rw-r-- 1 bottega bottega 3.1K Sep  4 18:36 the-rhyme3.txt
-rw-rw-r-- 1 bottega bottega 2.5K Sep  4 18:36 the-rhyme4.txt
-rw-rw-r-- 1 bottega bottega 4.4K Sep  4 18:36 the-rhyme5.txt
-rw-rw-r-- 1 bottega bottega 3.8K Sep  4 18:36 the-rhyme6.txt
-rw-rw-r-- 1 bottega bottega 4.1K Sep  4 18:36 the-rhyme7.txt

Cosa è successo? Quanti files abbiamo creato?

bottega@bottegadelbarbieri  ~  ls -lha the-rhyme{1..7}.txt
-rw-rw-r-- 1 bottega bottega 3.1K Sep 4 18:36 the-rhyme1.txt
-rw-rw-r-- 1 bottega bottega 2.2K Sep 4 18:36 the-rhyme2.txt
-rw-rw-r-- 1 bottega bottega 3.1K Sep 4 18:36 the-rhyme3.txt
-rw-rw-r-- 1 bottega bottega 2.5K Sep 4 18:36 the-rhyme4.txt
-rw-rw-r-- 1 bottega bottega 4.4K Sep 4 18:36 the-rhyme5.txt
-rw-rw-r-- 1 bottega bottega 3.8K Sep 4 18:36 the-rhyme6.txt
-rw-rw-r-- 1 bottega bottega 4.1K Sep 4 18:36 the-rhyme7.txt

Visualizziamo il terzo file giusto per vedere cosa abbiamo combinato:

bottega@bottegadelbarbieri  ~  cat the-rhyme3.txt |head  
PART THE THIRD.

There passed a weary time.  Each throat
Was parched, and glazed each eye.
A weary time! a weary time!
How glazed each weary eye,
When looking westward, I beheld
A something in the sky.

At first it seemed a little speck,

Ed ecco il terzo capitolo della novella. Non ci credete? Confrontiamo il terzo capitolo riportato nel file intero, e il terzo capitolo nel file esportato. Se il risultato di diff sarà nullo, allora i due saranno identici. Provare per credere:

bottega@bottegadelbarbieri  ~  wc -l the-rhyme3.txt
104 the-rhyme3.txt
bottega@bottegadelbarbieri  ~  cat the-rhyme-of-the-ancient-mariner.txt |grep -A104 "PART THE THIRD." > 3.txt
bottega@bottegadelbarbieri  ~  diff 3.txt the-rhyme3.txt
bottega@bottegadelbarbieri  ~ 

Abbiamo in buona sostanza diviso il file nei sette capitoli, utilizzando come delimitatore la parola “PART” e dicendo ad awk “fammi vedere quello che viene fra un PART e l’altro, in più esporta il contenuto e creami n files che comincino con un determinato nome”. Magic! Ovvio, awk non è solo questo ma è molto molto altro. E quindi… a voi i compiti per casa.

Alla prossima settimana!
jolek78

>> Indice <<
Puntata 25 < > Puntata 27

Il logo “Tux Linux” e’ stato realizzato e distribuito dall’artista deiby-ybied su Deviantart in licenza Creative Commons BY-NC-SA 3.0

jolek78 on Email
jolek78
Un tizio che pensava di essere uno scienziato. Si ritrovò divulgatore scientifico. Poi si addormentò su un aereo e si risvegliò informatico. Ma era sempre lui.

Lascia un commento

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