Friday, August 10, 2012

Un'infarinatura di sed

Cos'è sed? Sed è l'acronimo di stream editor. Sostanzialmente legge del testo riga per riga e lo trasforma in altro testo. Formattato però in un modo che ci fa più comodo.

Un esempio chiarirà tutto.

Prendiamo ad esempio un file, un mio file.

I seguenti pacchetti sono stati installati:
firebird2.5-common (2.5.0.26054~ReleaseCandidate3.ds2-1+b1)
firebird2.5-common-doc (2.5.0.26054~ReleaseCandidate3.ds2-1)
libfbclient2 (2.5.0.26054~ReleaseCandidate3.ds2-1+b1)
libgdiplus (2.6.7-3)
libglib2.0-dev (2.24.2-1)
libgluezilla (2.6-2)
libmono-accessibility1.0-cil (2.6.7-5)
libmono-accessibility2.0-cil (2.6.7-5)
libmono-bytefx0.7.6.1-cil (2.6.7-5)
libmono-bytefx0.7.6.2-cil (2.6.7-5)
libmono-c5-1.1-cil (2.6.7-5)
libmono-cairo1.0-cil (2.6.7-5)
libmono-cecil-private-cil (2.6.7-5)
libmono-cil-dev (2.6.7-5)
libmono-corlib1.0-cil (2.6.7-5)
libmono-cscompmgd7.0-cil (2.6.7-5)
libmono-cscompmgd8.0-cil (2.6.7-5)
libmono-data-tds1.0-cil (2.6.7-5)
libmono-data-tds2.0-cil (2.6.7-5)
libmono-data1.0-cil (2.6.7-5)
libmono-data2.0-cil (2.6.7-5)
libmono-db2-1.0-cil (2.6.7-5)
libmono-debugger-soft0.0-cil (2.6.7-5)
libmono-dev (2.6.7-5)
libmono-firebirdsql1.7-cil (2.6.7-5)
libmono-getoptions1.0-cil (2.6.7-5)
libmono-getoptions2.0-cil (2.6.7-5)
libmono-i18n-west1.0-cil (2.6.7-5)
libmono-i18n1.0-cil (2.6.7-5)
libmono-i18n2.0-cil (2.6.7-5)
libmono-ldap1.0-cil (2.6.7-5)
libmono-ldap2.0-cil (2.6.7-5)
libmono-management2.0-cil (2.6.7-5)
libmono-messaging-rabbitmq2.0-cil (2.6.7-5)
libmono-messaging2.0-cil (2.6.7-5)
libmono-microsoft-build2.0-cil (2.6.7-5)
libmono-microsoft7.0-cil (2.6.7-5)
libmono-microsoft8.0-cil (2.6.7-5)
libmono-npgsql1.0-cil (2.6.7-5)
libmono-npgsql2.0-cil (2.6.7-5)
libmono-oracle1.0-cil (2.6.7-5)
libmono-oracle2.0-cil (2.6.7-5)
libmono-peapi1.0-cil (2.6.7-5)
libmono-peapi2.0-cil (2.6.7-5)
libmono-posix1.0-cil (2.6.7-5)
libmono-profiler (2.6.7-5)
libmono-rabbitmq2.0-cil (2.6.7-5)
libmono-relaxng1.0-cil (2.6.7-5)
libmono-relaxng2.0-cil (2.6.7-5)
libmono-security1.0-cil (2.6.7-5)
libmono-sharpzip0.6-cil (2.6.7-5)
libmono-sharpzip0.84-cil (2.6.7-5)
libmono-sharpzip2.6-cil (2.6.7-5)
libmono-simd2.0-cil (2.6.7-5)
libmono-sqlite1.0-cil (2.6.7-5)
libmono-sqlite2.0-cil (2.6.7-5)
libmono-system-data-linq2.0-cil (2.6.7-5)
libmono-system-data1.0-cil (2.6.7-5)
libmono-system-data2.0-cil (2.6.7-5)
libmono-system-ldap1.0-cil (2.6.7-5)
libmono-system-ldap2.0-cil (2.6.7-5)
libmono-system-messaging1.0-cil (2.6.7-5)
libmono-system-messaging2.0-cil (2.6.7-5)
libmono-system-runtime1.0-cil (2.6.7-5)
libmono-system-runtime2.0-cil (2.6.7-5)
libmono-system-web-mvc1.0-cil (2.6.7-5)
libmono-system-web-mvc2.0-cil (2.6.7-5)
libmono-system-web1.0-cil (2.6.7-5)
libmono-system-web2.0-cil (2.6.7-5)
libmono-system1.0-cil (2.6.7-5)
libmono-tasklets2.0-cil (2.6.7-5)
libmono-wcf3.0-cil (2.6.7-5)
libmono-webbrowser0.5-cil (2.6.7-5)
libmono-windowsbase3.0-cil (2.6.7-5)
libmono-winforms1.0-cil (2.6.7-5)
libmono-winforms2.0-cil (2.6.7-5)
libmono0 (2.6.7-5)
libmono1.0-cil (2.6.7-5)
libmono2.0-cil (2.6.7-5)
libnunit-cil-dev (2.4.7+dfsg-6)
libnunit2.4-cil (2.4.7+dfsg-6)
libsqlite0 (2.8.17-6)
libwebkit1.1-cil (0.3-3)
mono-1.0-devel (2.6.7-5)
mono-1.0-gac (2.6.7-5)
mono-1.0-service (2.6.7-5)
mono-2.0-devel (2.6.7-5)
mono-2.0-service (2.6.7-5)
mono-complete (2.6.7-5)
mono-csharp-shell (2.6.7-5)
mono-devel (2.6.7-5)
mono-gmcs (2.6.7-5)
mono-jay (2.6.7-5)
mono-mcs (2.6.7-5)
mono-utils (2.6.7-5)
mono-xbuild (2.6.7-5)
monodoc-base (2.6.7-5)
monodoc-browser (2.6.2-3)
monodoc-manual (2.6.7-5)
prj2make-sharp (2.6.7-5)
zlib1g-dev (1:1.2.3.4.dfsg-3)


Viene dritto dritto dalla cronologia di synaptic. Sono dei pacchetti che ho sbagliato ad installare e che quindi dovrei rimuovere. Odio lasciare installati pacchi inutili sul pc, mi da l'idea di disordine e per di più occupa spazio.

Come potete notare, questo file è composto da tante righe e, a parte la prima, tutte hanno lo stesso formato:
nome del pacchetto (versione)
Il mio intento è quello di ottenere i soli nomi dei pacchetti, ordinati e docili come tante pecorelle in fila indiana. E poi dare in pasto questa lista di nomi al comando
sudo apt-get purge
per rimuoverli senza traccia. Tipo Mastro Lindo.

Il comando che ho usato è
sed -e '1d;s/(.*)//' da_rimuovere
Ora vi spiego tutto.

da_rimuovere è il file che è mostrato più sopra.

La parte contenuta tra gli apici è il comando di modifica che sed esegue sul file. C'è una cosa da tenere ben presente però: sed non modifica il file stesso! Bensì lo legge una riga dopo l'altra e scrive nel terminale il risultato dopo aver applicato la modifica.

In particolare, in questo caso, tra gli apici ci sono due comandi separati da un punto e virgola (;).

Il primo è 1d, ossia cancella (delete) la prima riga.
Il secondo è un comando di sostituzione, nella forma
s/stringa_da_sostituire/con_quest'altra_stringa/
Nel caso qui sopra, la stringa_da_sostituire consiste in due parentesi che racchiudono il numero di versione - che è sempre diverso - mentre la stringa sostituta è una stringa vuota. In pratica il risultato che si ottiene è quello di cancellare la stringa_da_sostituire.

Come faccio a identificare tutte le "parentesiaperta numerodiversione parentesichiusa"?
Posso farlo utilizzando un'espressione regolare. Un'espressione regolare è una sequenza di simboli che servono a identificare più stringhe con caratteristiche comuni fra loro.

Un'espressione regolare deve sempre essere racchiusa fra due barre (/  /). In questo caso, dato il suo uso all'interno del comando s///, non serve aggiungere altri slash.

L'espressione regolare si legge così:
(.*) tutte le stringhe che hanno una parentesi aperta, un qualsiasi numero di caratteri e una parentesi chiusa.
Il flag -e serve ad indicare a sed che quello che seguirà tra gli apici è il comando di modifica da eseguire.

Ecco fatto! Ora il comando è pronto per fare il suo dovere.

Potete creare uno script bash oppure digitare direttamente nel terminale questo comando:
sudo apt-get purge `sed -e '1d;s/(.*)//' da_rimuovere`
et voilà! PC pulito.

Per qualche lettura in più, da cui tra l'altro ho tratto questo breve tutorial, potete andare qui. Questa è solo la prima parte, qui la seconda e la terza. E' molto ben fatto e propone anche un piccolo ripasso sulle espressioni regolari.

A presto.