2011-11-04 9 views
90

W jaki sposób podzielić ciąg znaków, gdy zawiera on symbole rur | w nim. Chcę podzielić je na tablicę.Jak podzielić rozdzielany ciąg znaków na tablicę w awk?

Próbowałem

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

który działa dobrze. Jeśli mój ciąg jest jak "12|23|11", to w jaki sposób podzielić je na tablicę?

+3

Zauważ, że twoje dane wyjściowe łączą elementy tablicy bez separatora. Jeśli zamiast tego chcesz je oddzielić za pomocą 'OFS', umieść przecinki między nimi, dzięki czemu' print' zobaczy je jako oddzielne argumenty. – dubiousjim

Odpowiedz

145

Czy próbowałeś:

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

nie działa dla mnie :(czy to ze względu na długość ciągu? długość mojego ciągu wynosi 4000. wszelkie pomysły –

+0

@Mohamed Saligh, jeśli używasz systemu Solaris, musisz użyć */usr/xpg4/bin/awk *, biorąc pod uwagę długość ciągu znaków: –

+5

"nie działa dla mnie". z dwukropkami między echo wartościami i split zestaw do podziału na "|" Typo? Powodzenia dla wszystkich – shellter

1

Żart? :)

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

To moje wyjście:

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

więc myślę, że to działa po wszystkim ..

+0

to nie działało dla mnie :( –

+0

jest to ze względu na długość łańcucha? Ponieważ moja długość łańcucha wynosi 4000. wszelkie pomysły –

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

powinno działać.

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

Proszę być bardziej szczegółowe! Co masz na myśli mówiąc "to nie działa"? POST (lub komunikat o błędzie) dokładny wyjście, swoje OS i awk wersję:

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

Lub przy dzielone: ​​

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

Edycja: na Solaris trzeba użyć POSIX awk (/usr/xpg4/bin/awk) w celu prawidłowego przetworzenia 4000 pól.

+0

'for (i = 0' lub' for (i = 1'? – PiotrNycz

+0

i = 0, ponieważ używam ++ i po (nie i ++). –

+1

OK - Nie zauważyłem tego. Mocno wierzę, że bardziej czytelne byłoby 'for (i = 1; i <= n; ++ i) '... – PiotrNycz

2

Nie podoba mi się rozwiązanie echo "..." | awk ..., ponieważ wywołuje niepotrzebne wywołania systemowe fork i exec.

Wolę roztwór A Dimitre jest z małym skręcie

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

lub nieco krótszej wersji:

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

W tym przypadku płyta zebrała wyjście, które jest prawdziwym warunkiem, więc robi wydrukowane.

W tym konkretnym przypadku stdin przekierowanie może być oszczędzone z ustawieniem zmiennej wewnętrzny:

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

użyłem sporo czasu, ale w to może być zarządzany przez wewnętrzny ciąg manipulacji. W pierwszym przypadku oryginalny ciąg jest dzielony przez wewnętrzny terminator. W drugim przypadku zakłada się, że ciąg zawsze zawiera pary cyfr oddzielone separatorem znaków.

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} 

Wynik we wszystkich przypadkach jest

112312 
40

Aby podzielić ciąg do tablicy w awk używamy funkcji split():

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

Jeśli nie separator podano , używa parametru FS, który domyślnie jest przestrzenią:

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

Możemy dać separator, na przykład ::

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

co jest równoważne ustawieniu go przez FS:

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

W gawk można również separator jako wyrazy regularne:

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

a nawet zobaczyć co separator był na każdym kroku za pomocą czwarty parametr:

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

Zacytujmy stronę man:

split (łańcuch, tablica [, sep-pól [, SEPS]])

Podziel ciąg na części oddzielone spacerem i zapisz kawałki w tablicy i ciągi separatorów w tablicy seps. Pierwszy element jest przechowywany w tablicy 1, drugim elemencie w tablicy [2] i tak dalej. Wartość ciągu trzeciego argumentu, fieldsep, to wyrażenie regularne opisujące gdzie można podzielić ciąg znaków (tak jak FS może być wyrażeniem regularnym opisującym, gdzie podzielić rekordy wejściowe). Jeśli pominięto argument fieldsep, używana jest wartość FS. split() zwraca liczbę utworzonych elementów. seps jest rozszerzeniem gawk , z seps [i] będącym łańcuchem separatora między tablicą [i] a tablicą [i + 1]. Jeśli separator pól to pojedyncza spacja, to każda z białych spacji przechodzi w seps [0], a wszelkie końcowe białe znaki przechodzą w seps [n], gdzie n jest wartością zwracaną przez split() (tj. Liczbę elementów w tablicy).