2011-12-19 16 views
18

Che ci crediate o no, non riesco a trovare la risposta a quello che penserei sarebbe questa domanda molto semplice.loop su caratteri nella stringa di input utilizzando awk

In awk, come posso eseguire il looping della stringa di input carattere per carattere? Diciamo che volevo solo stamparli. C'è un array a cui posso accedere? O devo usare substr?

In sostanza, qualcosa di simile:

echo "here is a string" | awk ' 
{ for(i=0; i<[length of input string]; i++) 
    printf [value at index i in array x]; 
}' 

Francamente, mi vergogno.

risposta

32

È possibile convertire una stringa in un array utilizzando split:

echo "here is a string" | awk ' 
{ 
    split($0, chars, "") 
    for (i=1; i <= length($0); i++) { 
    printf("%s\n", chars[i]) 
    } 
}' 

Questo stampa i caratteri in verticale, uno per riga.

+0

in realtà, length() è un'estensione gawk AFAIK, non funziona su puro awk http://stackoverflow.com/questions/14720898/illegal-reference-to-an-array-in-awk-i- am-having-trouble-figuring-out-awk – vaxquis

+0

@vaxquis Non sono sicuro di cosa intendi per "puro" awk, ma 'length' è in POSIX. L'estensione gawk si applica agli array anziché alle stringhe. Fortunatamente, possiamo semplicemente passare 'length (chars)' a 'length ($ 0)'. –

+2

"puro" awk nel senso di "non alcun awk esteso" ... e sì, intendevo questo uso di length(); inoltre, puoi usare "len = split (...)" e successivamente "i <= len" con lo stesso risultato. – vaxquis

0

se avete gawk:

awk '$0=gensub(/(.)/,"\\1\n","g")' file 

prova:

kent$ echo "I am a String"|awk '$0=gensub(/(.)/,"\\1\n","g")' 
I 

a 
m 

a 

S 
t 
r 
i 
n 
g 
+0

c'è un modo per fare qualcosa con ciascun personaggio usando questo metodo o è solo una riformattazione della stringa? –

+1

può "fare qualcosa con ogni carattere". ma dipende da cosa è "qualcosa" – Kent

13

Per impostazione predefinita nel awk il Field Separator (FS) è space o tabs. Dato che hai menzionato di voler ricoprire ogni personaggio e non la parola, dovremo ridefinire il FS a zero. Qualcosa del genere -

[jaypal:~/Temp] echo "here is a string" | awk -v FS="" ' 
{for (i=1;i<=NF;i++) printf "Character "i": " $i"\n"}' 
Character 1: h 
Character 2: e 
Character 3: r 
Character 4: e 
Character 5: 
Character 6: i 
Character 7: s 
Character 8: 
Character 9: a 
Character 10: 
Character 11: s 
Character 12: t 
Character 13: r 
Character 14: i 
Character 15: n 
Character 16: g 
+0

AFAIK è possibile impostare FS = "" nel codice, non è necessario utilizzarlo al di fuori di esso ... – vaxquis

+0

hm. in realtà, funziona quando FS è impostato nel codice, ma in un modo leggermente diverso ... (ad esempio, la prima riga non viene analizzata) Qualche idea perché? – vaxquis

+2

È perché la prima riga è già stata letta prima con le impostazioni predefinite. –

5

Non tutte le implementazioni di awk supportano le soluzioni di cui sopra. In tal caso si potrebbe usare substr:

echo here is a string | awk '{ 
    for (i=0; ++i <= length($0);) 
    printf "%s\n", substr($0, i, 1) 
    }' 

P.S. In alcuni awk implementazioni di lunghezza senza argomenti default $ 0, cioè lunghezza e length ($ 0) sono equivalenti.

Problemi correlati