Объединить повторный префикс

2

У меня есть файл журнала, как:

Bug123:c:SomeComment
Bug222:c:SomeOtherComment
Bug123:c:SecondComment

Мне нужно произвести:

Bug123
    SomeComment
    SecondComment
Bug222
    SomeComment

Используя bash, я не могу придумать способ сделать это простым способом. Есть идеи?

Лев Уфимцев
источник
Напоминает мне о git shortlogкоманде.
Wildcard

Ответы:

4
$ awk 'BEGIN {FS=":"} {comments[$1][NR]=$3} END {for (bug in comments) { print bug; for (comment in comments[bug]) { print "    ",comments[bug][comment] } } }  ' /path/to/input
Bug123
     SomeComment
     SecondComment
Bug222
     SomeOtherComment

Это работает путем настройки многомерного массива во время чтения входного файла и последующего обхода результирующих данных в порядке, в котором видны «ошибки». С некоторыми небольшими изменениями это можно изменить для сортировки массива внешнего уровня.

DopeGhoti
источник
Я должен научиться как awk. Не знаю, как это работает, но выглядит изящно.
Лев Уфимцев
Это похоже vimна то, что поначалу выглядит очень тупо, но как только вы впитываете зубы, это очень быстро для изучения и может быть очень мощным инструментом. Смотрите также sed.
DopeGhoti
2

Вот интересный способ сделать это vi(или, на самом деле, exесли вы пропустите ведущие двоеточия для каждой команды):

:%!awk -F: '{a[$1];print} END {for (i in a) {print i}}'
:v/:/m0
:%!sort -st: -k1,1
:%s/^.*:/\t/

Объяснение:

Команда Awk печатает каждую строку как есть и выводит список всех уникальных первых полей в конце вашего файла.

vКоманда mOves на линию 0 (начало файла) все строки , которые не имеют каких - либо двоеточие. (Другими словами, список первых полей, выводимых из awk.)

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

Затем команда substitute превращает префикс каждой строки без заголовка во вкладку.


Результат на предоставленной вами информации:

Bug123
    SomeComment
    SecondComment
Bug222
    SomeOtherComment

Дополнительные объяснения:

:(двоеточие) - это то, что вы вводите, viчтобы начать команду ex-style.

%диапазон адресов в ex. Это означает «применить следующее действие / команду ко всем строкам в буфере (файле)».

При использовании с адресом !начинается «фильтр» в ex: строки, указанные адресом, подаются в качестве входных данных для указанной внешней команды и заменяются в буфере выходными данными этой команды.

-F: устанавливает разделитель полей Awk.

{}(фигурные скобки) используются в Awk для окружения запускаемых команд. Поскольку нет нет Awk адреса предшествующего фигурных скобок (в кавычках) одиночных, действия в фигурных скобках применяются к каждой строке ввода.

a[$1]создает элемент массива, используя первое поле текущей строки ( $1) в качестве индекса. Поскольку он не говорит = "whatever", элемент массива не имеет значения , но это не имеет значения; мы просто хотим, чтобы массив содержал этот элемент.

; завершает эту команду Awk.

printявляется командой Awk для печати текущей строки (по умолчанию) или любых переданных аргументов (как в последующем print i).

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

В forцикле выводит все индексы массива называется a. Которые являются дедуплицированными первыми полями файла журнала, в произвольном порядке.

Так много для команды Awk.

Команда v- это exкоманда, противоположная команде global. gвыполняет действие на всех линиях, соответствующих определенному шаблону. vвыполняет указанное действие на всех строках, НЕ соответствующих данному шаблону.

/начинается и заканчивается шаблон. Что только :в этом случае.

mозначает «двигаться». Таким образом, :v/:/m0in viперемещает все строки, которые не содержат двоеточий, в начало файла.

Остальные команды должны быть довольно понятными. :)

Wildcard
источник
Как мне запустить это в скрипте bash?
Лев Уфимцев
2

Perl однострочник

perl -MList::Util=uniq -F: -lane '
        push @keys, $F[0];
        push @{ $comment{$F[0]} }, $F[2];
    } END { 
        for $key (uniq @keys) {
            print $key;
            print "    $_" for @{$comment{$key}};
        }
' file
Гленн Джекман
источник
Это одна строка, для больших значений 1 :)
Джефф Шаллер
Конечно да. Одна команда. Новые строки - это просто символы внутри одного аргумента в кавычках для опции -e. И мои 1 самые большие, самые лучшие. Yuge.
Гленн Джекман