in reply to Global substitution and report

You can use while ( s///g ) safely (note the /g modifier). In scalar context, s///g will restart matching where the last match left off, so no infinite loop. However, tracing lines and particularly line numbers will be hard.

Since you mention changed lines and line numbers it appears that you expect changes to be limited to single lines, as opposed to changes spanning multiple lines. If so, you'd be much better off looping over the file line by line and logging changes as they happen. Note the $. variable, which will give you the line number.

Anno

Replies are listed 'Best First'.
Re^2: Global substitution and report
by Outaspace (Scribe) on Aug 27, 2007 at 08:43 UTC
    No, but the line where the substitution starts would be enough. So going line by line isn't really an option since this would disable multi-line substitutions. Isn't there a cool trick using the e modifier for substitutions?
      You could try to push the value of pos onto an array.

      $str =~ s{$pattern}{push @positions, pos $str; $substitution}eg

      I never worked with pos so I don't know if that helps you.

        It is nearly perfect, but
        $wFound = $szText =~ s/$szSearchText/push @wPos, pos $szText;$szReplac +eText/eg; foreach my $Line (@wLines) { $wLine = Convert::posToLine($szText, $Line); if ($wLines[-1] != $wLine) { push @wLines, $wLine; } print "Line: $wLine\n"; }
        doesn't replace correct if the replacement is something like "\L$1\E".
      How do you expect /e could help? It only changes the behavior of the substitution side of s///.

      One possibility is to step through substrings of the file content, starting at each new line. Here is a sketch:

      my $content = do { local $/; <DATA> }; my ( $ln, $start) = ( 1, 0); while ( $start < length $content ) { if ( substr( $content, $start) =~ s/.../.../ ) { print "line $ln changed\n"; } $start = 1 + index( $content, "\n", $start); ++ $ln; } __DATA__ aaa bbb ccc ddd eee
      Anno