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

коротша альтернатива може бути code(sed '1 ~ 2s / pattern / substitution /')
jaap

2

Просте тлумачення:

У першому рядку, що містить принаймні одне виникнення PATTERN, ви бажаєте проігнорувати його та надрукувати рядок як є. У другому рядку, що містить щонайменше одне виникнення PATTERN, ви хочете замінити перший екземпляр PATTERN заміною. На третьому рядку, що містить щонайменше одне виникнення PATTERN, ви хочете надрукувати рядок як є. У четвертому рядку, який містить щонайменше одне виникнення PATTERN, ви хочете замінити перший екземпляр PATTERN заміною. І так далі. Рядки, які не відповідають PATTERN, слід друкувати без змін.

Це легко зробити за допомогою 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 '}'

EDIT: Я просто перечитав питання і помітив більш складне тлумачення:

Замініть друге виникнення PATTERN у всьому документі ЗАМОВЛЕННЯ, незалежно від того, відбувається воно в тому ж рядку, що і перше виникнення, чи ні. Перше і третє випадки залиште без змін. І т.д.

Я вважаю, що це можна зробити і з Sed, хоча це набагато складніше, і я вважаю, що це залежить від регулярного вираження, яке буде використано. Я спробую щось розробити і опублікувати, але поки я дам цю відповідь простою версією, що є вище.


замініть свій test на quit і прийміть вклад, як-от { sed '...'; cat; } <inputлише одну заміну
mikeserv

1

Ви були дуже близько, просто пропустіть перший рядок:

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

Чому awkв цьому випадку має бути кращим інструментом?


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;}'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.