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

Hello Masters,
I want to find a pattern in all the files. Then i want to replace an exact specified pattern from every file. I am using the below command. However, the line "s#<--/--a8300-->.*?<--/a8300-->.##isg $_;" gives error. Could you please tell me, how can i use the replace command for all the files. Doesn't perl allow us to give the path of the file which we want to replace. There must be a way in perl and i am waiting for the masters to let us all know how to do that.

Thank You in advance.

#!root/perl5/perlbrew/perls/perl-5.13.4/bin/perl use feature say; #empty the file `>affectedlist.txt;` #will give the list of files which contains the pattern `grep -irl "<--/--a8300-->" ./* >> affectedlist.txt`; open(FILE,"<","affectedlist.txt") or die "Couldn't open file.$!"; foreach (<FILE>) { chomp($_); #Change filenames to unix readable e.g Nayab Rahil to Nayab\ Rahil $_=~ s#\s+#\\ #sg; #replace the pattern on every file. s#<--/--a8300-->.*?<--/a8300-->.##isg $_; #$_ is my filename }

Scalar found where operator expected at final.pl line 11, near
"s#<--/--a8300-->.*?<--/a8300-->.##isg $_"
syntax error at final.pl line 11, near "s#<--/--a8300-->.*?<--/a8300-->.##isg $_"
Execution of final.pl aborted due to compilation errors.

Please help me masters also if you can provide me good links to understand perl pattern matching. It would be really great for us.
Thanks again for your time.

Replies are listed 'Best First'.
Re: Replace a pattern in each file
by kcott (Archbishop) on Nov 01, 2013 at 12:13 UTC

    G'day nayabrahil,

    The problem is the " $_" near the end of "s#<--/--a8300-->.*?<--/a8300-->.##isg $_;".

    -- Ken

Re: Replace a pattern in each file
by Eily (Monsignor) on Nov 01, 2013 at 12:25 UTC

    Adding \ in front of the spaces is not necessary. This is useful in a shell command to show that the space isn't here to separate different arguments if your string isn't enclosed in quotes. But since your file name is in a string of its own, there's no ambiguity. Besides with s#\s+#\\ /sg; you would have replaced multiple spaces by only one.

    What you are searching for is Inplace Editing, you either have to add the -i option in your shebang (first line) or set the $^I variable. This means that all files opened with the <> construct will be edited inplace. while (<>) will go through each lines of each files in @ARGV (which you can set manually), and with inplace editing activated, anything you will print will be written to that file (so to let a line unchanged, you actually have to print it again).

    chomp(@ARGV = <FILE>); # put each line of FILE into @ARGV and remove t +he trailing \n while(<>) # for each filename in @ARGV { print s! <--/--a8300--> .*? <--/a8300-->. !!igr; }

    Maybe what you actually meant is actually s! <--/--a8300--> (.*?) <--/a8300-->. !$1!igr which translate to "get the content of <--/--a8300--> <--/a8300-->and keep only that", when what you wrote will delete the whole thing, tag and content. You could read perlretut for useful information on Perl regexen.

    Are you sure sed wouldn't have been enough though?

Re: Replace a pattern in each file
by RMGir (Prior) on Nov 01, 2013 at 12:16 UTC
    The problem is that you're not doing the search correctly.

    You wrote:

    s#<--/--a8300-->.*?<--/a8300-->.##isg $_;
    but the correct syntax is just
    s#<--/--a8300-->.*?<--/a8300-->.##isg;
    without the trailing ' $_' - the syntax of s/// is actually
    $string=~s/from/to/opts;
    with the $string being acted on defaulting to $_. Putting $_ after the expression makes no sense to perl...

    Mike