Direct errors and red flags:
Once you assign while ($variable = <$fh>)
the $_
is not set to what <$fh>
read; it is left as it has been (undefined here); so your regex, which matches it (by default), won't work
Parentheses to be matched as literal characters in regex need be escaped
The code processes all files from the current directory, <*>
-- which in this code may well contain the script itself as well, and there are no guards or checks
I assume that with ./replaced/
you mean replaced/
in the directory in which the script is, not in the current working directory (as pwd
); these are in general not the same. Please clarify.
Corrected, with other changes
use warnings;
use strict;
use feature qw(say);
use FindBin qw($RealBin);
use open ':std', ':encoding(UTF-8)';
my @files = grep { -f } @ARGV; # add further checks of user input
my $outdir = "$RealBin/replaced";
mkdir $outdir if not -d $outdir; # or use File::Path
foreach my $file (@files) {
my $fout = "$outdir/$file";
open my $fh, '<', $file or die "Can't open $file: $!";
open my $fh_out, '>', $fout or die "Can't open $fout: $!";
while (my $line = <$fh>) {
$line =~ s/Insertstoredprocedure \( / Insertstoredprocedure('$file',/g;
$line =~ s/SuccessSp\(\)/SuccessSp()('$file')/g;
print $fh_out $line;
}
say "done, $file --> $fout";
}
Comments on code in the question
Always start programs with use warnings;
and use strict;
The <*>
reads all entries from the current directory, what poses difficult questions; for one, that may include the script itself. More importantly, that way your script is hardwired with what data to process. Why not take user input instead? I changed it to use what is submitted on the command line, filenames presumably. Then on Linux you can invoke the script as
script.pl *.ext
You can still use script.pl *
if you must but then you need more checks, in particular to make sure to skip the script itself (if run from its directory). See for example this post
Always check input as appropriate. In this case you can at least ensure to process only plain files. I merely filter using -f
filetest operator but another option is to take input as submitted and then check, so that you can inform the user about inadequate input
I see no need to introduce $filename
; just use the topicalizer $file
If you work with UTF8 better use open pragma; then all files and streams are taken care of
Use lexical filehandles for everything, so for a file to be written as well
When reading a line from a file why not call it $line
? The "$variable
" in code is so generic that it provides no clue on what that variable is
Once you assigned to a named variable in the while
condition then $_
not set to what is read; that happens only with while (<$fh>)
. In this code it is undefined inside the loop body. So in the regex you need to use that variable, to which the line is assigned (and not leave it to default $_
)
Characters that have special meaning in regex must be escaped if you want to match them as literal characters, and parentheses are one of those. There are various ways to do that, I use your text and directly escape with \
(No need to escape in the replacement part)
It is in principle a good idea to define patterns as separate variables using qr
operator. Then you can escape all special characters in them using quotemeta
I have no way to know whether your (corrected) regex does what is intended so I could only fix the obvious error. Please show samples of data and of needed output.