[comp.lang.perl] search and replace string from a script

merlyn@iwarp.intel.com (Randal L. Schwartz) (04/24/91)

In article <1991Apr23.180034.7349@progress.com>, root@progress (Root of all Evil) writes:
| Is there any way within ex (or some other text processing utility) to
| access the nth occurrence of a pattern?  What I'd like to do is search
| a file for the nth occurrence of a pattern and then change that pattern
| but no others.  I've tried using ex:
| 
| ex -s FILE << QUIT
| /STRING1/n s/STRING1/STRING2/
| wq!
| QUIT
| 
| but this only places me n lines after the first occurrence of STRING1.
| Any ideas?  I'd like to avoid writing to a temporary file.

perl -pe '/STRING1/ && (++$n == 20) && s/STRING1/STRING2/' <in >out

OK, so the syntax is cryptic; do it C-like if you want:

perl -pe 'if (/STRING1/ && (++$n == 20)) { s/STRING1/STRING2/; }' <in >out

or even (more verbosely):

perl -pe 'if (/STRING1/) { s/STRING1/STRING2/ if ++$n == 20; }' <in >out

(well, maybe not more verbosely, then... :-)  Or even:

perl -pe 's/STRING1/STRING2/ if /STRING1/ && (++$n == 20);' <in >out

All of these presume "20" is your magic occurance.  Season to taste.

print "Just another Perl hacker," # Perl is available from all GNU sites...
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/

merlyn@iwarp.intel.com (Randal L. Schwartz) (04/26/91)

In article <1991Apr25.040751.1991@ttsi.lonestar.org>, root@ttsi (System) writes:
| >perl -pe '/STRING1/ && (++$n == 20) && s/STRING1/STRING2/' <in >out
| >
| >perl -pe 'if (/STRING1/ && (++$n == 20)) { s/STRING1/STRING2/; }' <in >out
| >
| >perl -pe 'if (/STRING1/) { s/STRING1/STRING2/ if ++$n == 20; }' <in >out
| >
| >perl -pe 's/STRING1/STRING2/ if /STRING1/ && (++$n == 20);' <in >out
| >
| >All of these presume "20" is your magic occurance.  Season to taste.
| >
| >print "Just another Perl hacker," # Perl is available from all GNU sites...
| 
| These all presume only one occurrence or first occurrence per line.
| Is that the requirement?  How would you handle counting multiple 
| occurrences per line in perl?  Thanks for posting the solutions above.

OK, now you did it.  You asked me to get ugly.  Hang on to your hat...

perl -pe 's/STRING1/(++$n == 20) ? "STRING2" : $&/ge' <in >out

You might need to look at this one for a while to figure out what's
happening.  Trust me, it'll be good for you. :-)

(And if you can't figure it out, I know this great book on the
subject... :-)

print "Just another Perl hacker,";
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/