10

Is there a way to tell sed to replace the pattern on every second occurrence? Or at least on every second line? (Sure it's possible with a script, but I was asking myself if sed can do it to).

Edit

I found

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

But it replaced every first occurence, not the second.

Example

Input file:

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

Desired output:

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

see https://stackoverflow.com/questions/5858200/sed-replace-every-nth-occurrence

The solution uses awk rather than sed, but "use the right tool for the job". It may or may not be possible to do in sed but, even if it is, it will be a lot easier in a tool like awk or perl.

  • 1
    Using what i've learn there I maid sed -e 'n;s/2004-2009/6e législature/g' which solved my problem. – Matthieu Riegler Aug 1 '12 at 12:27
  • 1
    that won't get every second occurrence, it will search for your pattern on every second line. i.e. skip the 1st, 3rd, 5th, 7th, etc lines. of course, that might still work for your particular document. – cas Aug 1 '12 at 22:19
  • Yup I know. that's what I needed actually. – Matthieu Riegler Aug 2 '12 at 0:27
14
sed 's/pattern/replacement/2'

Will replace the second occurrence on every line that has the pattern.


if you have GNU sed:

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

Starting from line one 1, the line after it will be added to the pattern space N then the s command will replace the second occurrence of the pattern. then sed will move two lines down ~2 and repeat.

  • I don't want the second but every second. – Matthieu Riegler Aug 1 '12 at 11:45
  • I have one pattern per line. That won't work. – Matthieu Riegler Aug 1 '12 at 11:53
  • would've been nice to know that prior. So the pattern happens on line one, two, three and four (etc), and you want to replace the pattern on line two, four, etc? – llua Aug 1 '12 at 12:00
  • a shorter alternative may be code(sed '1~2s/pattern/replacement/') – jaap Jun 22 '15 at 14:30
2

The simple interpretation:

On the first line that contains at least one occurrence of PATTERN you want to ignore it and print the line as-is. On the second line that contains at least one occurrence of PATTERN you want to replace the first instance of PATTERN with REPLACEMENT. On the third line that contains at least one occurrence of PATTERN you want to print the line as-is. On the fourth line that contains at least one occurrence of PATTERN you want to replace the first instance of PATTERN with REPLACEMENT. And so on. Lines that do not match PATTERN should be printed without change.

This can be easily done with Sed like so:

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

Or, with less whitespace and a shorter label:

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

EDIT: I just reread the question and spotted the harder interpretation:

Replace the second occurrence of PATTERN in the entire document with REPLACEMENT, whether it occurs on the same line as the first occurrence or not. Leave the first and third occurrences unaltered. Etc.

I believe this can be done with Sed as well, though it's MUCH trickier and I believe it is dependent on the regular expression to be used. I will try to work something out and post it, but I will let this answer stand with the simple version above for now.

  • replace your test with a quit and take input like, { sed '...'; cat; } <input for only a single replacement – mikeserv Dec 10 '16 at 13:56
1

You were very close, just skip the first line:

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

Why should awk be the better tool in this case?

0

One symbol pattern within the one line: sed 's/(a[^a]*)a/\1c/g'

Every second pattern (only one pattern match per line may appear. if two or more matches per one line will appear, only the second one will be replaced)

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;}'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.