2016-04-22 4 views
2

Меня всегда беспокоило, что sed не имеет команды j, например ed.Желая, чтобы у sed был эквивалент для удобной команды j ed

This question спрашивает, как присоединиться к линиям в целом, и есть куча хороших ответов, многие из которых показывают другие инструменты, такие как awk и perl. И есть также некоторые решения sed, но все они связаны с использованием команды s, чтобы буквально отредактировать новую строку, что является решением, которое по разным причинам поражает меня как kludgey.

Теперь sed также имеет некоторые неясные команды, имеющие отношение к пространствам «удержание» и «узор», которые я никогда не выяснял, как использовать. Я всегда предполагал - BICBW - что пространство удержания - это ответ sed на команду j, если только я мог бы выяснить, как ее использовать.

Так что мой вопрос на сегодняшний день - и это больше на интеллигенте, как практический вопрос - это, есть хороший, безопасный, достаточно краткий способ сделать эквивалент

sed /pat/j 

Это для каждой строки, содержащей шаблон pat, присоедините его к следующей строке (то есть, как и ed, если бы я использовал g/pat/j/).

Как я уже сказал, это интеллектуальный вопрос. Я знаю, как присоединяться к линиям, используя другие инструменты, или используя sed и команду s на цитируемой литеральной новой строке. Но мне кажется, что это должен быть лучший способ.

(Или, может быть, я должен просто перехватить копию sed.c и взломать в надлежащем j команды.)

ответ

3
sed '/pat/{$!{N;s/\n/ /}}' 

Если pat матчи и строка не последняя строка, добавьте следующую строку в этой линии, а затем заменить \n с пространством

Ref: how-can-i-use-sed-to-replace-a-multi-line-string

+0

Aha! Поэтому, если я правильно понимаю это, 'N' почти похоже на' j', за исключением того, что он вставляет новую строку. Очень интересно.(Ваш пример не работал для меня напрямую, мне пришлось использовать 'sed -e '/ pat/N' -e '/ \ n//' '. В вашем примере хранится жалоба« bad flag in substitute command:'} «Не знаю, если это ограничение с моей версией sed или что.) –

+0

Он использует не переносные конструкции, поэтому поведение в разных seds будет отличаться. Таким образом, решение в вашем комментарии и также будет вести себя по-разному в разных садах. –

+0

@SteveSummit Он использует GNU 'sed', который не требует новых строк после каждой команды. Удобен для «однострочных». – Kusalananda

1

Я знаю, что это трудно глотать, но если честно - СЭД для простых замен на отдельных линиях и для anyt hing else вы должны использовать awk. Я считаю, что sed невероятно полезен и использовал его почти каждый день в течение 30 лет, но все конструкторы sed, которые делали что-либо, кроме простых замещений на отдельных линиях, стали устаревшими в середине 1970-х годов, когда был изобретен awk.

$ seq 4 | awk '{printf "%s%s", s, $0; s=ORS} /2/{s=OFS} END{print ""}' 
1 
2 3 
4 

Как насчет присоединения линий на 2s:

$ seq 10 | awk '{printf "%s%s", $0, (NR%2?OFS:ORS)}' 
1 2 
3 4 
5 6 
7 8 
9 10 

Попробуйте модифицирования SED сценарий, который соединяет 2 линии, чтобы присоединиться к 5 строк вместо. По сравнению с простым, очевидным AWK подстройке изменения числа 2 на номер 5:

$ seq 10 | awk '{printf "%s%s", $0, (NR%5?OFS:ORS)}' 
1 2 3 4 5 
6 7 8 9 10 

выше будет работать во всех awks на всех операционных системах и легко модернизируется с минимальными изменениями, если/когда ваши требования изменить - два очень важные причины, по которым вы должны учиться использовать awk для этого вместо sed.

+0

Спасибо, Эд, я знаю все об awk, использую его каждый день, но это не то, что я спросил. –

+0

@SteveSummit понял, но этот вопрос и ответы, которые он получит, будут здесь на долгие годы и прочитаны многими людьми, поэтому ИМХО важно, чтобы этот ответ присутствовал ради них, если не для вас. –