[comp.unix.shell] search and replace string from a script

root@progress.COM (Root of all Evil) (04/24/91)

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.

Thanks...

   Rich

P.S.  I use the Bourne shell.

------------------------------------------------------------------------------
Rich Lenihan                 UUCP: mit-eddie!progress!rich
Progress Software Corp.      Internet: rich@progress.com
5 Oak Park                   >-   Insert funny stuff here  -<
Bedford, MA  01730           >-Draw amusing symbols, logo's-<
USA                          >-     or characters here     -<

subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (04/24/91)

In article <1991Apr23.180034.7349@progress.com> root@progress.COM (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

If you have perl, you can say this:

% perl -pi -e 'if (/STRING1/) { s/STRING1/STRING2/ if (++$num == N); }' FILE

Isn't perl cool :-)

		-Kartik


--
internet# rm `df | tail +2 | awk '{ printf "%s/quotas\n",$6}'`

subbarao@phoenix.Princeton.EDU -| Internet
kartik@silvertone.Princeton.EDU (NeXT mail)  
SUBBARAO@PUCC.BITNET			          - Bitnet

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'..."====/

root@ttsi.lonestar.org (System) (04/25/91)

In article <1991Apr23.215804.8366@iwarp.intel.com> merlyn@iwarp.intel.com (Randal L. Schwartz) writes:
>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...

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.


-- 
Mark S. Evans                 Tandem Telecommunications Systems Inc.
Phone: 214-516-6201           850 E. Central Parkway
Fax:   214-516-6801           Plano, TX 75074
Mail:  mse@ttsi.lonestar.org

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'..."====/