awk 'BEGIN { i=0; }
/^reference:/ { ref[i++] = $0; }
/^sid:/ { for(j=0; j<i; j++) { print ref[j]; print; } i=0; }' inputfile > outputfile
Пояснение:
BEGIN { i=0; }
Инициализируйте переменную, чтобы убедиться, что она интерпретируется как числовое значение 0
, а не как пустая строка ""
. /^reference:/ { ref[i++] = $0; }
Для каждой строки, начинающейся с reference:
(^
, есть привязка к началу строки ), скопируйте всю строку $0
в элемент массива ref[i]
и увеличьте индексi++
/^sid:/ {... }
для каждой строки, начинающейся с sid:
... for(j=0; j<i; j++) {... }
Поскольку i
указывает на элемент массива после последнего использованного, циклически перебрать все элементы массива, которые были записаны, используя индекс j
, print ref[j];
вывести содержимое элемента массива, т.е. сохраненную reference:
строку print;
напечатать текущую строку, то есть строку sid:
i=0;
сбросить индекс массива на начало следующей группы из reference:
строк Сценарий основан на следующих предположениях:
reference:
строк, за которыми следует sid:
строка sid:
. В исходном вопросе я предположил неправильное направление преобразования. Второй скрипт конвертирует в обратном направлении:
awk 'BEGIN { oldsid=""; ref=""; }
/^reference:/ { ref=$0; }
/^sid:/ { if(oldsid != $0) { if(oldsid != "") print oldsid; } if(ref!="")print ref; oldsid=$0; }
END { if (oldsid != "") print oldsid; }' inputfile > outputfile
Пояснение:
BEGIN { oldsid=""; ref=""; }
Инициализируйте переменные для ясности, на самом деле это не обязательно./^reference:/ { ref=$0; }
Для каждой строки, начинающейся с reference:
, сохраните строку $0
в переменной ref
, пока не печатайте ее. /^sid:/ {... }
Для каждой строки, начинающейся с sid:
... if(oldsid != $0) { if(oldsid != "") print oldsid; }
Если строка sid:
изменилась сейчас, последняя строка reference:
, сохраненная в ref
, принадлежит новой строке sid:
, поэтому мы ее пока не печатаем. Если oldsid
не пусто, мы можем напечатать его сейчас, так как предыдущий блок из reference:
строк с таким же sid:
закончен. oldsid
будет пустым, когда мы найдем первый sid:
. if(ref!="")print ref;
Если у нас есть сохраненный reference:
, распечатайте его сейчас. (Либо мы только что закрыли предыдущий блок соответствующей строкой sid:
, либо теперь мы знаем, что текущий reference:
имеет тот же sid:
, что и предыдущий. )Проверка на пустую строку на самом деле не нужна, так как я предполагаю, что каждой строке sid:
предшествует строка reference:
. oldsid=$0;
сохранить текущую строку sid:
для сравнения, когда мы получим следующую. Текущая строка еще не напечатана. END { if (oldsid != "") print oldsid; }
В конце выведите последнюю сохраненную строку sid:
, если она есть. (Если входной файл пуст, здесь не будет напечатана пустая строка.)Этот сценарий основан на этих предположениях:
reference:
следуетsid:
reference:
и sid:
с одной и той же строкой sid:
следуют друг за другом