Это работает с GNU SED, я не думаю, что это зависит от каких-либо специфических для GNU расширений, но я не знаю.
echo "$yourdata" | sed -ne '1{h;d}; /^TAG1$/ {n; /^TAG2$/{n;N;N; /\nTAG3$/ {s///; H; n;N;N; /\nTAG4$/ {s///; H; g; s/\n\n/-/gp; q; } } } }'
Результат: альфа-браво-чарли
Как это работает? Сначала мы говорим sed "-n", что мы не хотим ничего печатать, если мы специально не скажем [p] rint.
Первый блок выражения sed - «1 {h; d}». Это говорит, что когда мы читаем строку 1, сохраняем эту строку в старом буфере [h], затем [d] выбираем ее из рабочего буфера, чтобы мы прочитали следующую строку и пропустили ее через выражение sed с самого начала.
При чтении последующих строк блок «1 {...}» будет пропущен.
Мы ничего не соответствуем, пока не достигнем линии TAG1. На этом этапе мы выполняем длинный блок {...}. Это говорит о том, что сначала прочитайте строку [n] ext, перезаписав строку TAG1, которая была в буфере. Если буфер сейчас TAG2, мы выполняем следующий внутренний блок {...}. Это сначала читает строку [n] ext, перезаписывая то, что уже находится в буфере. Следующие две команды: «N; N». Это означает, что нужно прочитать следующие 2 строки, но добавить их в рабочий буфер, а не перезаписывать их. Если рабочий буфер теперь соответствует /\nTAG3 $ /, то мы выполняем следующий внутренний блок {...}. Это говорит, что сначала "s ///", другими словами, заменить пустую строку на последнее найденное выражение. Это удаляет «\nTAG3» из конца рабочего буфера, оставляя «\nbravo». Затем мы делаем [H], который добавляет это в буфер хранения. ([h] перезаписывает буфер удержания, [H] добавляет к нему). Таким образом, теперь буфер удержания содержит первую строку "alfa", а затем следующую строку «\nbravo». К ним присоединяется новая строка, поэтому у нас действительно есть «alfa \n \nbravo». Мы позаботимся о двух новых строках позже.
Мы продолжаем идти, пока не получим "alfa\n\nbravo\n\ncharly" в буфере удержания. Затем мы говорим [g] и буфер удержания (перезаписывая все, что находится в рабочем буфере). Мы делаем «s /\n\n /- /» для этого, чтобы превратить двойные переводы строки в тире. Мы добавляем флаги "g" и "p" в конец команды [s], чтобы подстановка работала глобально (т.е. не просто выполняет одну подстановку, а затем останавливается), а результат после подстановки печатается [p].
Тогда нам [q] uit, нам не нужно читать остальную часть входного потока.