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:
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 comandonome del pacchetto (versione)
per rimuoverli senza traccia. Tipo Mastro Lindo.sudo apt-get purge
Il comando che ho usato è
Ora vi spiego tutto.sed -e '1d;s/(.*)//' da_rimuovere
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:
et voilà! PC pulito.sudo apt-get purge `sed -e '1d;s/(.*)//' da_rimuovere`
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.