2

У меня есть файл, содержимое которого выглядит следующим образом:

alfa
[many lines here]
TAG1
TAG2

bravo
TAG3

charlie
TAG4
[many lines here]

где TAG1, TAG2, TAG3 и TAG4 являются фиксированными строками, а альфа, браво и чарли время от времени меняются, и я хочу извлечь:

alfa-bravo-charlie

Какую именно команду sed я должен использовать? Я не знаю, как работать с многострочным рисунком. :(

PS: я использую sed для windows.

2 ответа2

3

Это работает с 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, нам не нужно читать остальную часть входного потока.

1

Из вашего примера не совсем понятно, что вы пытаетесь сделать. Похоже, вы пытаетесь удалить все содержимое файла, кроме набора из трех маркеров, которые вы хотите объединить вместе. Вам не нужно sed для этого, вы можете просто набрать:

echo alfa-bravo-charlie

И вы достигли своей цели. Если вы просто хотите удалить содержимое между "alfa" и "charlie", вы можете использовать скрипт sed следующим образом:

/charlie/ a\
alfa-bravo-charlie
/alfa/,/charlie/ d

Если это не то, что вы хотите сделать, это может помочь, если вы поясните свой пример.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .