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

when I run my code the variable is given a value and then it becomes emput when it leaves the block on the first loop. On all subsequent loops the variable holds the data.
====================================================== if ( $line =~ /^Public Key Type:/ ) { $public_key_type = scalar <DATA> for 1; $public_key_type =~ s/^\s+//; $public_key_type =~ s/\s+$//; $public_key_type = "$public_key_type"; $public_key_type =~ s/\R//g; print "$public_key_type\n"; } ======================================================
The above works, but I need to print the variable later in my code. When I try to print the variable $public_key_type outside the block the variable becomes empty. Does anyone have a suggestion on how I can keep the data in the variable once it leaves the block?

Replies are listed 'Best First'.
Re: variable has value but then become empty
by stevieb (Canon) on Sep 09, 2015 at 14:04 UTC

    First, please wrap your code, data and expected output within <code></code> tags.

    You should always use strict; and use warnings;. I believe the problem you're having is that you don't define $public_key_type prior to the loop. perl lexicalizes variables, so if you define something within a scope, that variable will not be accessible outside of that scope; this is by design.

    You don't show the beginning of the while loop, so I've guessed. Try something like the following (untested):

    use strict; use warnings; my $public_key_type; while (my $line = <DATA>){ if ( $line =~ /^Public Key Type:/ ) { $public_key_type = scalar <DATA> for 1; $public_key_type =~ s/^\s+//; $public_key_type =~ s/\s+$//; $public_key_type =~ s/\R//g; } } print "$public_key_type\n";

    -stevieb

      perl lexicalizes variables, so if you define something within a scope, that variable will not be accessible outside of that scope ...

      I think this is quite misleading. It doesn't make any distinction between lexical and package variables. The point should be clearly made that an automatically created or "autovivified" variable (which is what  $public_key_type might possibly be; no way to know from the code fragment shown) is a package global and visible (update: and accessible) everywhere. The following example runs with warnings, but of course can only run without strict (and a good thing, too!):

      c:\@Work\Perl\monks>perl -le "use warnings; ;; while (! $xyzzy || $xyzzy < 5) { ++$xyzzy; } print $xyzzy; ;; print for grep m{ xyzzy \z }xms, keys %main::; " 5 xyzzy
      Printing the  %main:: package namespace hash after the code is run shows autovivification of the variable globally.


      Give a man a fish:  <%-{-{-{-<

Re: variable has value but then become empty
by 1nickt (Canon) on Sep 09, 2015 at 14:09 UTC

    Hi Randy_j53,

    In Perl a variable will exist until the end of the scope it's created in. That's why we create variables with my(), in order to limit them to a restricted scope (block, package, subroutine, etc).

    my $foo = 'bar';
    If a variable is declared inside a block, it won't be available outside the block.
    #!/usr/bin/perl use strict; use warnings; sub foo { my $bar = 'baz'; } foo(); print $bar; # error
    Compare with:
    #!/usr/bin/perl use strict; use warnings; my $bar = 'baz'; sub foo { $bar = 'qux'; } foo(); print $bar; # prints 'qux'
    Here's a PerlMonks tutorial on scoping. You'll find many more resources if you use the Super Search and look up 'scoping.'

    And please, always put use strict; and use warnings; at the top of your code. These are Perl's safety features, and one of the main things they do is alert you when you are not getting variable scope right.

    Hope this helps!

    Edit: oops, missed the sub calls!

    The way forward always starts with a minimal test.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: variable has value but then become empty
by locked_user sundialsvc4 (Abbot) on Sep 09, 2015 at 14:44 UTC

    Also consider the implications of the following bit of code, which compiles and runs without errors or warnings:

    use strict; use warnings; my $foo = "bar "; { my $foo = "foo "; print $foo; } print $foo;
    Whose output is:   foo bar

    The definition of $foo which exists within the anonymous block conceals, without warning, the variable of the same name that exists outside the block.   Two entirely distinct values are maintained, each referred-to at different times and in different scopes by the same variable name.  Within the block, the value "bar " cannot be reached, and there is nothing to alert you to the probably-unintentional conflict.

    This is not “incorrect” behavior.   It is, in fact, by design, although it might be slightly different from other languages you have used (and whose error, warning, and informational messages you might have come to rely upon).   This it just might be yet-another reason why “global variables are not a particularly good idea.”