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

Incredibly simple question i'm sure but I can't seem to figure it out. I'm attempting to perform an in-place search and replace on multiple .txt files within a directory - and want this to be confined to a specific column only. I've tried:

perl -pi -w -lane '$F[0] = s/AAA/BB/;' *.txt

But this replaces AAA with BB globally, rather than within $F[0] only. Why is this happening?

Replies are listed 'Best First'.
Re: In-place search and replace confined to a specific column
by Eily (Monsignor) on Jan 29, 2016 at 10:45 UTC

    As Discipulus pointed out, using both -p and -n doesn't make much sense. And you'll have to use the correct operator as Corion told you

    Your issue is that -p prints $_ no matter what, it doesn't print back the splitted data of @F. You have to do that yourself: $" = qq(\t);$_="@F"; You'll find $" in perlvar.

    Edit: you can try this to see the code that perl generates from your one liner: perl -MO=Deparse -pae '$_ = @F'

    LINE: while (defined($_ = <ARGV>)) { our(@F) = split(' ', $_, 0); $_ = @F; } continue { die "-p destination: $!\n" unless print $_; }

    Edit: replaced $"="\t"; by  $" = qq(\t); because the first one looked like a syntax error.

      Brava Eily!

      never tought to use -MO=Deparse to inspect a oneliner! this trick push me even more up in the dark oneliner side of the source..

      Anyway -p seems to superseed -n in both order, results are equal:

      perl -MO=Deparse -p -n -e 1 LINE: while (defined($_ = <ARGV>)) { '???'; } continue { die "-p destination: $!\n" unless print $_; } -e syntax OK perl -MO=Deparse -n -p -e 1 LINE: while (defined($_ = <ARGV>)) { '???'; } continue { die "-p destination: $!\n" unless print $_; } -e syntax OK'

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: In-place search and replace confined to a specific column
by Corion (Patriarch) on Jan 29, 2016 at 09:52 UTC

    You're using the wrong operator. You are assigning to $F[0] instead of using regex binding.

    perl -pi -w -lane '$F[0] =~ s/AAA/BB/;' *.txt

    could work.

      I did try this originally, but unlike '=', '=~' fails to replace anything at all unless -w and -pi are removed - but that then prevents me from batch processing all .txt files.
        hello, are not -p and -n togheter, a nonsense?

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.