Sed: заменить шаблон на каждую вторую строку?

10

Есть ли способ сказать, sedчтобы заменить шаблон в каждом втором случае? Или хотя бы на каждой второй строке? (Конечно, это возможно с помощью сценария, но я спрашивал себя, sedможно ли это сделать).

редактировать

я нашел

sed -e "s/pattern/replacement/g;n"

Но он заменял каждый первый случай, а не второй.

пример

Входной файл:

I have a pattern in each line
Also the second line has the pattern
Another pattern here
And -- you guess it -- a pattern

Желаемый вывод:

I have a pattern in each line
Also the second line has the replacement
Another pattern here
And -- you guess it -- a replacement
Мэтью Риглер
источник

Ответы:

6

см. /programming/5858200/sed-replace-every-nth-occurrence

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

саз
источник
1
Используя то, что я там узнал, я горничная, sed -e 'n;s/2004-2009/6e législature/g'которая решила мою проблему.
Матье Риглер
1
это не будет происходить каждое второе вхождение , оно будет искать ваш шаблон в каждой второй строке . т.е. пропустить 1-ю, 3-ю, 5-ю, 7-ю и т. д. строки. конечно, это все еще может работать для вашего конкретного документа.
Cas
Да, я знаю. это то, что мне было нужно на самом деле.
Матье Риглер
14
sed 's/pattern/replacement/2'

Заменит второе вхождение в каждой строке, имеющей шаблон.


если у вас есть GNU sed:

sed '1~2N ; s/pattern/replacement/2'

Начиная с первой строки 1, строка после нее будет добавлена ​​в пространство шаблона, Nпосле чего sкоманда заменит второе вхождение шаблона. затем sedпереместится на две строки вниз ~2и повторите.

llua
источник
Я не хочу второго, но каждую секунду.
Матье Риглер
У меня есть один шаблон на строку. Это не сработает.
Матье Риглер,
было бы приятно узнать это до. Таким образом, шаблон происходит в строке один, два, три и четыре (и т. Д.), И вы хотите заменить шаблон в строке два, четыре и т. Д?
llua
более короткая альтернатива может быть code(sed '1 ~ 2s / pattern /
replace
2

Простая интерпретация:

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

Это можно легко сделать с помощью Sed следующим образом:

sed -e '/PATTERN/ { :inside' -e 'n;s//REPLACEMENT/;t' -e 'b inside' -e '}'

Или с меньшим количеством пробелов и более короткой меткой:

sed -e '/PATTERN/{:i' -e 'n;s//REPLACEMENT/;t' -e 'b i' -e '}'

РЕДАКТИРОВАТЬ: Я просто перечитал вопрос и заметил более сложную интерпретацию:

Замените второе вхождение PATTERN во всем документе на REPLACEMENT, независимо от того, встречается ли оно в той же строке, что и первое вхождение, или нет. Оставьте первое и третье вхождения без изменений. И т.п.

Я полагаю, что это может быть сделано и с Sed, хотя это НАМНОГО сложнее, и я полагаю, что это зависит от используемого регулярного выражения. Я постараюсь что-то придумать и опубликовать, но пока оставлю этот ответ в простой версии выше.

Wildcard
источник
замените test на quit и примите входные данные, как { sed '...'; cat; } <inputтолько для одной замены
mikeserv
1

Вы были очень близки, просто пропустите первую строку:

sed '1n;s/pattern/replacement/;n'

Почему должен awkбыть лучший инструмент в этом случае?

Philippos
источник
0

Один символ в одной строке: sed 's / (a ​​[^ a] *) a / \ 1c / g'

Каждый второй шаблон (может появиться только одно совпадение с шаблоном на строку. Если появятся два или более совпадений на одну строку, будет заменен только второй)

echo -e "test\nreplace_me\ntest\ntest\nreplace_me\nreplace_me\nreplace_me" | \
sed '/replace_me/{:a;N;/replace_me.*replace_me/!Ta;s/replace_me/replaced/2;}'
порыв
источник