Bash: Trasposizioni

Venerdì mattina, tempo soleggiato e pomeriggio in permesso, domani è sabato, nulla potrà rovinarmi la giornata. A parte un mio collega che entra in ufficio e se ne esce con una frase che comincia con – abbiamo trovato il baco ieri sera – e finisce con – dobbiamo trasporre le cinquecento matrici che usiamo per i test. L’entusiasmo per la prima parte della frase si smorza subito non appena realizzo cosa sottindende la seconda: niente pausa caffè (tè nel mio caso) prima di aver modificato i file visto che con i test fermi nessun altro potrà lavorare.

Mi metto subito al lavoro ed inizialmente penso di fare un programmino in C. Quando mi ricordo (shame on me) che non ho tanto fresca la sintassi del linguaggio penso che farei prima con un paio di righe di bash piuttosto che rinfrescarmi la memoria.

Il problema che devo risolvere consiste nel manipolare i file che contengono le matrici (una per file) e salvare al loro posto la matrice trasposta.

La trasposta di una matrice è una matrice in cui sono state scambiate le righe con le colonne (in pratica la prima riga della matrice diventa la prima colonna della trasposta, la seconda riga rappresenta la seconda colonna e così via…)

La soluzione è più semplice del previsto e la riporto subito prima di commentarla. In particolare mi è piaciuto (perché risalito d’un tratto dagli abissi della memoria) l’uso di xargs che forse potrebbe lasciare qualcuno interdetto

#!/bin/bash
for i in $(seq 1 $3)
do
  head $1 -n $2 | cut -d \  -f $i | xargs
done

Lo script non fa altro che predere una matrice, rivoltarla e stamparla in standard output. A questo punto redirigere l’output in un nuovo file diventa banale, come è banale processare tutti i file in automatico. Torniamo allo script ed al suo commento, Chiamiamolo ad esempio trasponi.

Viene invocato come trasponi file 4 3 per trasporre una matrice, file, di 4 righe per 3 colonne. Sull’output avremo una matrice di 3 righe per 4 colonne. Nel file le matrici sono memorizzate per righe ed in ogni riga un elemento è separato dagli altri da uno spazio.

La riga di codice che crea le diverse righe è head $1 -n $2 | cut -d \ -f $i | xargs e potrebbe anche essersi ridotta in cut $1 -d \ -f $i | xargs ma l’ho scritta in quel modo per evidenziare il numero di righe della matrice da elaborare.

La prima parte del pipe seleziona la colonna da trasformare, l’ultima si occupa di assemblarla come riga.

xargs, di solito, si usa per leggere dallo standard input dei parametri da passare ad un comando. Se non viene specificato si assume che il comando a cui passare i parametri sia echo.
Un altro utilizzo di xargs, magari non così convenzionale, è mettere tutti su una riga i parametri che gli vengono passati in input uno per volta (sfruttando il fatto che il parametro predefinito sia echo).

Le potenzialità di xargs, tra l’altro, non si esaurscono qui, ci sono altre funzioni a cui può assolvere oltre quella canonicamente riconosciuta di “fornitore di parametri”. Potenzialità che saranno oggetto di un ulteriore post.

E questo, per ora, è tutto

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 )

Foto di Facebook

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

Connessione a %s...