Successivo: , Precedente: , Su: Separatori di campo   [Contenuti][Indice]


4.5.2 Usare regexp come separatori di campo

La precedente sottosezione ha illustrato l’uso di caratteri singoli o di stringhe semplici come valore di FS. Più in generale, il valore di FS può essere una stringa contenente qualsiasi espressione regolare. Se questo è il caso, ogni corrispondenza nel record con l’espressione regolare separa campi. Per esempio, l’assegnamento:

FS = ", \t"

trasforma ogni parte di una riga in input che consiste di una virgola seguita da uno spazio e una tabulazione in un separatore di campo.

Per un esempio meno banale di espressione regolare, si provi a usare spazi singoli per separare campi nel modo in cui sono usate le virgole. FS può essere impostato a "[ ]" (parentesi quadra sinistra, spazio, parentesi quadra destra). Quest’espressione regolare corrisponde a uno spazio singolo e niente più. (vedi la sezione Espressioni regolari). C’è una differenza importante tra i due casi di ‘FS = " "’ (uno spazio singolo) e ‘FS = "[ \t\n]+"’ (un’espressione regolare che individua uno o più spazi, tabulazioni o ritorni a capo). Per entrambi i valori di FS, i campi sono separati da serie (ricorrenze adiacenti multiple) di spazi, tabulazioni e/o ritorni a capo. Comunque, quando il valore di FS è " ", awk prima toglie lo spazio vuoto iniziale e finale dal record e poi stabilisce dove sono i campi. Per esempio, la seguente pipeline stampa ‘b’:

$ echo ' a b c d ' | awk '{ print $2 }'
-| b

Invece la pipeline che segue stampa ‘a’ (notare lo spazio extra intorno a ogni lettera):

$ echo ' a  b  c  d ' | awk 'BEGIN { FS = "[ \t\n]+" }
>                                  { print $2 }'
-| a

In questo caso, il primo campo è nullo, o vuoto. Il taglio degli spazi vuoti iniziale e finale ha luogo anche ogniqualvolta $0 è ricalcolato. Per esempio, si consideri questa pipeline:

$ echo '   a b c d' | awk '{ print; $2 = $2; print }'
-|    a b c d
-| a b c d

La prima istruzione print stampa il record così come è stato letto, con lo spazio vuoto intatto. L’assegnamento a $2 ricostruisce $0 concatenando insieme $1 fino a $NF, separati dal valore di OFS (che è uno spazio per default). Poiché lo spazio vuoto iniziale è stato ignorato quando si è trovato $1, esso non fa parte del nuovo $0. Alla fine, l’ultima istruzione print stampa il nuovo $0.

C’è un’ulteriore sottigliezza da considerare quando si usano le espressioni regolari per separare i campi. Non è ben specificato nello standard POSIX, né altrove, cosa significhi ‘^’ nella divisione dei campi. Il ‘^’ cerca corrispondenze solo all’inizio dell’intero record? Oppure ogni separatore di campo è una nuova stringa? Di fatto versioni differenti di awk rispondono a questo quesito in modo diverso, e non si dovrebbe far affidamento su alcun comportamento specifico nei propri programmi. (a.b.)

Di sicuro, BWK awk individua con ‘^’ solo l’inizio del record. Anche gawk funziona in questo modo. Per esempio:

$ echo 'xxAA  xxBxx  C' |
> gawk -F '(^x+)|( +)' '{ for (i = 1; i <= NF; i++)
>                             printf "-->%s<--\n", $i }'
-| --><--
-| -->AA<--
-| -->xxBxx<--
-| -->C<--

Successivo: , Precedente: , Su: Separatori di campo   [Contenuti][Indice]