Используйте скрипт bash для извлечения имен определенных типов и соответствующих номеров - PullRequest
2 голосов
/ 22 февраля 2012
A: XXX (Done after 2 rounds)
A: YYY (Done after 1 rounds)
A: ZZZZ (Done after 4 rounds)
A: XXX (Done after 2 rounds)
A: ZZZZ (Done after 1 rounds)
A: YYY (Done after 2 rounds)
A: YYY (Done after 1 rounds)

Для приведенного выше файла я хочу извлечь определенные имена, например, XXX, YYY, ZZZZ, а также количество раундов для каждого имени.

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

XXX 2 2
YYY 1 2 1
ZZZZ 4 1

Я чувствую, что должен использовать sed или awk, но не уверен, как их использовать. У кого-нибудь есть хорошие решения? Большое спасибо.

Ответы [ 3 ]

5 голосов
/ 22 февраля 2012
awk '{ names[$2] = names[$2] " " $5; } END { for (name in names) print name " " names[name] }' file

Пояснение:

Каждая строка ввода передается команде names[$2] = names[$2] " " $5, которая создает массив с именем names, индексы которого не являются числовыми - это слова, которые отображаются в виде 2-го поля в ваших строках ввода: XXX, YYY и ZZZZ. Их значения накапливают соответствующие числа в 5-м поле каждой строки.

Когда входной файл исчерпан, END перебирает имена индексов, печатая каждое имя, за которым следует строка с набранными числами.

1 голос
/ 22 февраля 2012

Мне нравятся структуры данных Perl (хэш массивов) для чего-то вроде этого:

perl -lane '
        push @{$packets{$F[1]}}, $F[4]
    } 
    END {
        foreach $name (keys %packets) {print join(" ", $name, @{$packets{$name}})
    }
'
0 голосов
/ 22 февраля 2012

Это может работать для вас:

cut -d' ' -f2,5 file |
sort -sk1,1 |
sed ':a;$!N;s/^\(\(\S\+\).*\)\n\2/\1/;ta;P;D'
XXX 2 2
YYY 1 2 1
ZZZZ 4 1

Объяснение:

  • Извлечь поля 2 и 5, например, в первой строке XXX 2, используя cut -d' ' -f2,5 file
  • Сортировать по первому полю, но сохранить порядок sort -sk1,1
  • Sed объединяет строки, в которых первое поле совпадает, и добавляет второе поле.sed ':a;$!N;s/^\(\(\S\+\).*\)\n\2/\1/;ta;P;D'

Эта команда sed работает следующим образом:

  • Создание метки :a
  • Добавление новой строки к текущей строке (пробелPS) тогда следующая строка, если это не последняя строка.$!N
  • Используя команду подстановки, сопоставьте первое поле текущей строки с первым полем предыдущей строки, а затем удалите его вместе с предыдущим переводом строки.s/^\(\(\S\+\).*\)\n\2/\1/
  • Если замена прошла успешно, переходите к метке.ta
  • Если замена не удалась, выведите PS до первой новой строки.P
  • Удалите PS до и включая первую новую строку, затем начните новый цикл без обновления PS.D
...