Using Perl in-line edits, how do you insert a line after the Nth occurence of a string?

Viewed 918

Looking for a method to insert a line after the Nth occurence of a given string.

The following is close to what I'm looking for, but is line number based, versus based on the Nth occurrence of a given string.

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt
4 Answers

The following will add a line of xyz after the second occurrence of the string abc:

perl -pi -e '/abc/&&++$n==2 and $_.="xyz\n"' inFile.txt

No need to initialize the count if warnings aren't enabled.

perl -pe'$_.="foo\n" if /bar/ && ++$c == 5'

The modulus (%) operator is great for detecting every Nth.

perl -pe'$_.="foo\n" if /bar/ && ++$c % 5 == 0'

[It's always nice to see someone checked the FAQ! How do I change, delete, or insert a line in a file, or append to the beginning of a file?.]

Here's how I would do it:

% perl -ni -e 'print; print "Inserted\n" if (/time/ && ++$c) == 3' input.txt

The counter variable $c is incremented by the return value of the match operator. It's 0 if it doesn't match and 1 if it does match (it's used in scalar context so even with a /g it only matches once at most). After that update to $c it's compared to the value you want.

Here's input.txt:

 First time
 Second time
 Third time
 Fourth time

And the result:

 First time
 Second time
 Third time
 Inserted
 Fourth time

Alternately, you make make this a little shorter with -p which automatically puts a print at the end. In that case you end up inserting the line before the next line instead of after the previous line (and that may be a problem if you don't have enough lines to come before something):

% perl -pi -e 'print "Inserted\n" if (/time/ && ++$c) == 4' input.txt

And, you might consider upgrading to v5.28 if you are not using it already. In-place editing gets a bit safer by writing to a temp file first then replacing the source file once the program completes successfully.

If you're looking to repeat after every fifth occurrence of the string, you can create a variable in a BEGIN block and monitor it:

perl -n -e 'BEGIN{$c=0;} print; $c++ if /one/; if ($c==5){print "Put after fifth entry\n";$c=0}' inFile.txt
Related