2011-11-04 9 views
90

Come dividere la stringa quando contiene i simboli di tubo | in esso. Voglio dividerli in serie.Come dividere una stringa delimitata in una matrice in awk?

ho cercato

echo "12:23:11" | awk '{split($0,a,":"); print a[3] a[2] a[1]}' 

che funziona bene. Se la mia stringa è come "12|23|11", allora come li divido in un array?

+3

Si noti che l'output concatena gli elementi dell'array, senza separatore. Se invece volessi che fossero separati con 'OFS', rimuovi le virgole tra di loro, facendo in modo che' print' li veda come argomenti separati. – dubiousjim

risposta

145

Hai provato:

echo "12|23|11" | awk '{split($0,a,"|"); print a[3],a[2],a[1]}' 
+0

non funziona per me :(è che a causa della lunghezza della stringa? la mia lunghezza di corda è 4000. Qualsiasi idea –

+0

@Mohamed Saligh, se sei su Solaris, devi usare */usr/xpg4/bin/awk *, data la lunghezza della stringa. –

+5

'non funziona per me'. con i due punti tra i valori echoed e split set per dividere su '|' ??? Typo? Buona fortuna a tutti. – shellter

1

Joke? :)

Come su echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'

Questa è la mia uscita:

p2> echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}' 
112312 

quindi credo che stia funzionando dopo tutto ..

+0

non funzionava per me :( –

+0

è che a causa della lunghezza della stringa ?, poiché la lunghezza della stringa è 4000. Qualsiasi idea –

2
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}' 

dovrebbe funzionare.

3
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}' 
11

prega di essere più specifico! Cosa intendi con "non funziona"? post l'uscita esatta (o messaggio di errore), il sistema operativo e la versione awk:

% awk -F\| '{ 
    for (i = 0; ++i <= NF;) 
    print i, $i 
    }' <<<'12|23|11' 
1 12 
2 23 
3 11 

Oppure, utilizzando spezzati:

% awk '{ 
    n = split($0, t, "|") 
    for (i = 0; ++i <= n;) 
    print i, t[i] 
    }' <<<'12|23|11' 
1 12 
2 23 
3 11 

Edit: su Solaris è necessario utilizzare il POSIX awk (/usr/xpg4/bin/awk) per elaborare correttamente 4000 campi.

+0

' per (i = 0' o ' per (i = 1'? – PiotrNycz

+0

i = 0, perché uso ++ i dopo (non i ++). –

+1

Ok - Non ho notato questo. Credo fermamente che più leggibile sarebbe 'for (i = 1; i <= n; ++ i) '... – PiotrNycz

2

Non mi piace la soluzione echo "..." | awk ... in quanto chiama chiamate di sistema non necessarie fork e exec.

preferisco la soluzione di un Dimitre con un po 'di torsione

awk -F\| '{print $3 $2 $1}' <<<'12|23|11' 

o una versione po' più corta:

awk -F\| '$0=$3 $2 $1' <<<'12|23|11' 

In questo caso il record di uscita messo insieme, che è una vera condizione, quindi diventa stampato.

In questo caso specifico il reindirizzamento stdin può essere risparmiato con impostando una variabile interna:

awk -v T='12|23|11' 'BEGIN{split(T,a,"|");print a[3] a[2] a[1]}' 

Ho usato piuttosto un po ', ma in questo potrebbero essere gestiti mediante manipolazione stringa interna. Nel primo caso la stringa originale viene divisa dal terminatore interno. Nel secondo caso si presume che la stringa contenga sempre coppie di cifre separate da un separatore di un carattere.

T='12|23|11';echo -n ${T##*|};T=${T%|*};echo ${T#*|}${T%|*} 
T='12|23|11';echo ${T:6}${T:3:2}${T:0:2} 

Il risultato è in ogni caso

112312 
40

Per dividere una stringa in un array in awk si usa la funzione split():

awk '{split($0, a, ":")}' 
#   ^^^^^^ 
#   | | | 
#  string | delimiter 
#    | 
#    array to store the pieces 

Se non viene dato alcun separatore utilizza lo FS, che per impostazione predefinita è lo spazio:

$ awk '{split($0, a); print a[2]}' <<< "a:b c:d e" 
c:d 

Siamo in grado di dare un separatore, ad esempio ::

$ awk '{split($0, a, ":"); print a[2]}' <<< "a:b c:d e" 
b c 

che equivale a impostare attraverso il FS:

$ awk -F: '{split($0, a); print a[1]}' <<< "a:b c:d e" 
b c 

In gawk si può anche fornire il separatore come regexp:

$ awk '{split($0, a, ":*"); print a[2]}' <<< "a:::b c::d e" #note multiple : 
b c 

E anche vedere ciò che il delimitatore era su ogni passo utilizzando il suo quarto parametro:

$ awk '{split($0, a, ":*", sep); print a[2]; print sep[1]}' <<< "a:::b c::d e" 
b c 
::: 

Citiamo la pagina man:

split (string, array [, fieldsep [, seps]]

Dividere la stringa in pezzi separati da fieldsep e memorizzare i pezzi nella matrice e le stringhe di separazione nell'array seps. Il primo pezzo viene memorizzato nell'array 1, il secondo pezzo nell'array [2] e così via. Il valore di stringa del terzo argomento, fieldsep, è un'espressione regolare che descrive in cui dividere la stringa (analogamente a quanto può essere una espressione regolare di FS in cui si trovano i record di input suddivisi in ). Se fieldep è omesso, viene utilizzato il valore di FS. split() restituisce il numero di elementi creati. seps è un'estensione gawk , con seps [i] è la stringa di separazione tra array [i] e array [i + 1]. Se fieldep è un singolo spazio, qualsiasi spazio bianco iniziale su va a seps [0] e qualsiasi spazio bianco finale va a seps [n], dove n è il valore di ritorno di split() (cioè il numero di elementi nella matrice).