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


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

пробовал

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

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

7 108

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-страницу:

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

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