Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

A question was posed to me about using substitution to perform concatenation -- more as a question as to whether substitution is flexible enough to do so rather than is this the best way to use the tools Perl provides.

So, I wrote the following as an innocuous brute force attempt:

die 'insufficient arguments' unless @ARGV == 1; open(IN, $ARGV[0]) or die "unable to open '$ARGV[0]'"; while (my $line = <IN>) { my $prefix = sprintf '%4d', $.; $line =~ s/$line/$prefix: $line/; print $line; } close IN;
However, the output is:
$ perl test.pl test.pl 1: die 'insufficient arguments' unless @ARGV == 1; open(IN, $ARGV[0]) or die "unable to open '$ARGV[0]'"; while (my $line = <IN>) { my $prefix = sprintf '%4d', $.; $line =~ s/$line/$prefix: $line/; print $line; 7: } 8: close IN; $
Adding use strict; modifies the output to:
$ perl test.pl test.pl 1: use strict; 2: die 'insufficient arguments' unless @ARGV == 1; open(IN, $ARGV[0]) or die "unable to open '$ARGV[0]'"; while (my $line = <IN>) { my $prefix = sprintf '%4d', $.; $line =~ s/$line/$prefix: $line/; print $line; 8: } 9: close IN; $
Can you help elucidate why these results are what is shown above? I see the same behavior using ActiveState 5.8.4 and 5.6 on FreeBSD 4.11.

Thanks for your candor.

Replies are listed 'Best First'.
•Re: concatenation through substitution?
by merlyn (Sage) on Dec 30, 2004 at 19:37 UTC
    $line =~ s/$line/$prefix: $line/;
    Ooops. You're treating the contents of $line as a regex on the left side of a substitute. Many of those lines have regex-significant characters, so they don't match themselves.

    You can do this the hard way:

    $line =~ s/\Q$line/$prefix: $line/;
    Or the much easier way:
    $line =~ s/^/$prefix: /;

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: concatenation through substitution?
by waswas-fng (Curate) on Dec 30, 2004 at 21:22 UTC
    Regex work fine, but seems like using a fork to spread butter and cut bread. Whats wrong with:
    1: die 'insufficient arguments' unless @ARGV == 1; 2: open(IN, $ARGV[0]) or die "unable to open '$ARGV[0]'"; 3: while (my $line = <IN>) { 4: my $prefix = sprintf '%4d', $.; 5: print "$prefix: $line"; 6: } 7: close IN; 8: or 1: die 'insufficient arguments' unless @ARGV == 1; 2: open(IN, $ARGV[0]) or die "unable to open '$ARGV[0]'"; 3: while (my $line = <IN>) { 4: my $prefix = sprintf '%4d: ', $.; 5: print $prefix . $line; 6: } 7: close IN; 8:
    ?


    -Waswas
      or 1: die 'insufficient arguments' unless @ARGV; 2: open(IN, $ARGV[0]) or die "unable to open '$ARGV[0]': $!"; 3: while (my $line = <IN>) { 4: printf "%4d: %s", $., $line; 5: } 6: close IN;
        Or for that matter:
        while (<>) { printf '%4d: %s', $., $_ }

      Regex work fine, but seems like using a fork to spread butter and cut bread. Whats wrong with:

      Well, your suggestion doesn't use a fork to spread butter and cut bread, that's what's wrong! The point of the exercise is to figure out whether you can use a fork to spread butter and cut bread. It's not to spread butter and to cut bread, no, the essence is to use the fork. Read what the OP says:

      A question was posed to me about using substitution to perform concatenation -- more as a question as to whether substitution is flexible enough to do so rather than is this the best way to use the tools Perl provides.

      So, your suggestion utterly fails to answer the question - by avoiding the thing being queried.