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


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

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


Я должен научиться как 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перемещает все строки, которые не содержат двоеточий, в начало файла.

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


Как мне запустить это в скрипте 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.
— Гленн Джекман
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.