Как разбить строку с разделителями в массив в awk?

как разделить строку, когда она содержит символы трубы | в нем. Я хочу разделить их в массив.

пробовал

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

работает нормально. Если моя строка похожа на "12|23|11" тогда как я могу разделить их в массив?

7 ответов


вы пробовали:

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

разбить строку на массив в awk мы используем функцию split():

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

если разделитель не задан, он использует FS, по умолчанию используется пробел:

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

мы можем дать разделитель, например ::

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

что эквивалентно установке его через FS:

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

в gawk вы также можете предоставить разделитель в виде регулярного выражения:

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

и даже посмотрите, что разделитель был на каждом шаге, используя его четвертый параметр:

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

давайте процитируем man page:

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

разделить строку на части, разделенные fieldsep и хранить части в массиве и строках-разделителях в массиве seps. Первый кусок хранится в массиве1, вторая часть в массиве[2] и так далее. Этот строковое значение третий аргумент, fieldsep, является регулярным выражением, описывающим где разбить строку (так как FS может быть регулярным выражением, описывающим, где разделить входные записи). Если fieldsep опущен, используется значение FS. Split() возвращает количество созданных элементов. seps-это gawk расширение, причем seps[i] является строкой-разделителем между массивом[i] и массив[i+1]. Если fieldsep-это одно пространство, то любое ведущее пробелы переходят в seps[0] , а любые конечные пробелы - в seps[n], где n - возвращаемое значение split () (т. е. количество элементов в массиве).


пожалуйста, поконкретнее! Что значит "не работает"? Опубликуйте точный вывод (или сообщение об ошибке), вашу ОС и версию awk:

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

или, используя split:

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

Edit: on Солярис вам понадобится POSIX awk ( / usr/xpg4/bin / awk) для правильной обработки 4000 полей.


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

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

должны работать.


мне не нравится echo "..." | awk ... решение, как он называет ненужным fork и = ' <<<'12|23|11'

в этом случае выходная запись вместе, которая является истинным условием, поэтому она печатается.

в данном случае stdin перенаправление можно сэкономить с установкой на awk внутренние переменная:

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

Я КШ довольно долго, но в Баш это может управляться внутренней манипуляцией строками. В первом случае исходная строка разделяется внутренним Терминатором. Во втором случае предполагается, что строка всегда содержит пары цифр, разделенных одним символом-разделителем.

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}

результат во всех случаях

112312

шутка? :)

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

Это мой выход:

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

Так что я думаю, это работает в конце концов..