Comandi composti

dennis-ritche-unix-quote

Una delle cose più meravigliose di Linux (in realtà Unix) è che i comandi (una volta tutto avveniva via terminale e comandi, niente WIMP) è che possono –anzi spesso devono– essere composti tra di loro. Come i mattoncini del Lego direbbe Marco. Ma siccome la metafora è sua non la uso; non parliamone più. Ma è così.

Come mi hanno chiesto due baldi giovani (ehi! il figlio di P. che lavorava con me quando è nato 😀 come passa il tempo!) riguardo al caso dell’altro giorno, questo.

Si vorrebbe modificare questo output:
c0

trasformandolo così:

c1

Si può fare vero? Certo 😀
Ci sono due comandi che sembrano fatti proprio per quello, sed e AWK.
Adesso un vecchio come me (o sono solo io) farebbe in un altro modo, come ha sempre fatto ma sì, l’idea sembra OK. Proviamo…
Salta fuori che non è immediato, non come sembrava. Per fortuna c’è il Web; e StackOverflow (al solito), qui.

Vediamo prima sed:

c2

Uh! panico! no, dai, vediamo…
Non devo spiegare la pipe | vero? già fatto tante volte, quindi resta la parte di sed.
Cominciando dalla fine s/\n/ /g è semplicissimo sostituire ogni (g) carattere a-capo (\n) con uno spazio.
La prima parte è più interessante. Intanto sono 3 comandi separati da  punto-virgola.
:a è una label, un etichetta ci serve per ritornare lì con b (branch).
N appende la riga che legge al testo precedente.
$ è l’ultima riga dell’input e quindi salto a a solo se non ci sono arrivato (! al solito vale not).
Facile vero? O non tanto?

L’alternativa è AWK:

c3

Intanto lo lanciamo sostituendo il valore di RS (record separator) con l’opzione -v e con l’opzione -F risettiamo il field separator.
A questo punto basta dire di scrivere il valore del primo field con 1. Ma dobbiamo ricordargli che è cambiato per cui $1=$1.
Facile vero? O non tanto?

joke-unix-friendly

Yep! non tanto facile; anzi piuttosto macchinoso e siamo stati fortunati a trovarlo fatto nel Web (anche se il titolo era sbagliato) :grin.

Ma però, io che sono vecchio la soluzione ce l’avevo fin da subito (anche questa peraltro si trova facilmente nello stesso sito):

c4

echo fa l’eco di quello che gli viene passato; nel nostro caso però il testo non ce l’abbiamo ancora. Niente panico con $() eseguo il comando tra le parentesi con priorità maggiore, pronto per echo.

Facile vero?
Fare la stessa cosa con un linguaggio di programmazione (quello che volete) sarebbe decisamente più lungo. Magari più facile ma meno elegante.
Lasciato come esercizio :mrgreen:

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • Theodore  Il 23 maggio 2015 alle 16:00

    Appena l’ho visto ho pensato:
    primes 2 10 | { while read n ; do printf “%s ” $n ; done ; echo ” }

    La bourne shell è una droga.

    • juhan  Il 23 maggio 2015 alle 16:09

      Alternativa valida, bella ma forse non semplicissima — promosso 😉

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: