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

here is the simple find and replace code I wrote to find and replace a line in config files.</P

#!/usr/bin/perl use warnings; use strict; use File::Copy; my($fileName) = $ARGV[0]; print("$fileName \n"); my($find) = "cps***"; my($replace) = "nat***"; if(-e $ARGV[0]) { my($copy) = "$ARGV[0].bak"; copy($ARGV[0], $copy) or die "File cannot be copied. \n"; } else { print "File does not exist. \n"; exit; } open(INPUT,"$copy") or die 'Cannot open file: $!\n'; open(OUTPUT,">$ARGV[0]"); while(<INPUT>){ $_ =~ s/$find/$replace/g; print OUTPUT $_; } close INPUT; close OUTPUT; unlink($copy); print("File $fileName correctly pointed\n"); exit 0;
when I run this code I get the following error message:
Variable "$copy" is not imported at /home/test/.put_on_nat.pl line 25. (Did you mean &copy instead?) Variable "$copy" is not imported at /home/test/.put_on_nat.pl line 35. (Did you mean &copy instead?) Global symbol "$copy" requires explicit package name at /home/test/.pu +t_on_nat.pl line 25. Global symbol "$copy" requires explicit package name at /home/test/.pu +t_on_nat.pl line 35.

so I tried to put 'my()' on the variable name and recieved this error message:

"my" variable $copy masks earlier declaration in same scope at /home/t +est/.put_on_nat.pl line 35. Can't declare string in "my" at /home/test/.put_on_nat.pl line 25, nea +r ")) "

am I misunderstanding the package name? i thought that declaring it as 'my()' was how you declared a package name, but I am new to perl and still trying to wrap my head around it all. Thanks in advance for your help.

Replies are listed 'Best First'.
Re: Find and Replace
by toolic (Bishop) on Mar 29, 2010 at 19:15 UTC
    You get the error message because that variable is not scoped properly. Declare it outside of the if/else block:
    my($find) = "cps***"; my($replace) = "nat***"; my $copy; if(-e $ARGV[0]) { $copy = "$ARGV[0].bak"; copy($ARGV[0], $copy) or die "File cannot be copied. \n"; }

    See also: Variables and Scoping

Re: Find and Replace
by moritz (Cardinal) on Mar 29, 2010 at 19:16 UTC
    my declares a lexical variable in the current scope. Your program has the structure
    if (...) { # you declare a variable here my $copy; ... # use it here } # and use it here - WRONG

    You can't use the variable outside the block you declare it in. So move the declaration outside of the block.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Find and Replace
by kennethk (Abbot) on Mar 29, 2010 at 19:22 UTC
    You are having a scoping issue. When you use my, your variable is lexically scoped to the current block. In your case, that is the if block, and so you $copy variable is out of scope by the time you get to line 25. Instead, your my needs to be at the same level as you usage, which means script level. You could just move the my before the block and initialize within the block, but I think it would be more logical to replace the if block with

    unless (-e $ARGV[0]) { print "File does not exist. \n"; exit; } my($copy) = "$ARGV[0].bak"; copy($ARGV[0], $copy) or die "File cannot be copied. \n";

    or if (not... if you don't like unless blocks.

Re: Find and Replace
by amedico (Sexton) on Mar 30, 2010 at 04:28 UTC
    FYI, Perl already has all the necessary scaffolding in place to do this as a command-line one-liner:
    perl -ibak -pe 's/cps\*\*\*/nat***/g' filename