in reply to Perl substitute with the nth match

> OF COURSE I can do this in a loop. Or with a /e

Can you? I can, too:

perl -pe 's/cat/++$i/ge' file

There's no special variable that counts matches. But there's one that's incremented with each line of input: $.. So if we could tell Perl that cat instead of a newline is the line delimiter... but of course we can do that! That's what $/ is for.

perl -pe 'BEGIN { $/ = "cat" } chomp; $_ .= $. unless eof' file

Update: which can be rewritten to use substitution as you originally wanted:

perl -pe 'BEGIN { $/ = "cat" } s{$/}{$.}' file

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^2: Perl substitute with the nth match
by LanX (Saint) on Jan 13, 2023 at 13:50 UTC
    > > OF COURSE I can do this in a loop.

    > s/cat/++$i/ge

    interestingly it's possible to avoid /e in an efficient inside-out (TIMTOW) loop version of m///

    say pos($txt) while $txt =~ m/cat/g

    Now with s/// this kind of works, but isn't efficient because pos will be reset each time

    use v5.12; use warnings; use Data::Dump qw/pp dd/; my $txt = <<'___'; cat dog cat mouse eel cat housecat catamaran fish ___ say 'm-pos:', pos($txt) while $txt =~ m/cat/g; my $cnt=1; while ($txt =~ s(cat)($cnt)x) { say "s-pos:", pos($txt) // "undefined"; $cnt++; } say $txt;
    m-pos:3 m-pos:11 m-pos:25 m-pos:34 m-pos:38 s-pos:undefined s-pos:undefined s-pos:undefined s-pos:undefined s-pos:undefined 1 dog 2 mouse eel 3 house4 5amaran fish

    and no, using s///g would do the outer loop only once, tho there might be a way to force a single replace with (?FAIL) ... probably?

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery