http://qs1969.pair.com?node_id=570891

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

Hello Fellow Monks of perl;

I'm having difficulties in declaring the $text field as global to the entire program. I've separated the slurp of the file into a separate scope, so that I can read the conversion parameter's line by line. How can I use the same $text that I slurped, in my while statement. What I have is a list of bogus names and clock numbers that I am globally replacing in my text file.

#!/usr/lib/perl use strict; use warnings; use Data::Dumper; { my $file1 = '/home/greyfox/data/TBLLOTUSNOTESPYRAMID.txt'; print "$file1\n"; local( $/, *INPUT ); open( INPUT, $file1 ) or die "Can't open $file1 $!\n"; our $text = <INPUT>; close INPUT or die "Can't close INPUT $!"; } my $file2 = '/home/greyfox/data/ConvTable.txt'; open (FD, $file2) or die "Can't open $file2 $!"; while (my $line = <FD>) { my @data = split (/\t/, $line); $data[0] =~ s/[ ]+$//g; $data[0] =~ s/,./,/g; our $text =~ s/$data[0]/$data[2]/g; our $text =~ s/$data[1]/$data[3]/g; print our $text; } close FD or die "Can't close FD $!";

As Bartles & Jaymes would say "Thank you for your support"

-- Grey Fox
Perl - Hours to learn lifetime to master.

2006-09-03 Retitled by Arunbear, as per Monastery guidelines
Original title: 'Use of a global scaler.'

Replies are listed 'Best First'.
Re: Use of a global scalar
by friedo (Prior) on Sep 02, 2006 at 21:49 UTC
    Using our within a block makes the variable a package global only within that block. To make the global valid throughout the entire file, simple put our $text at the top. You're also re-declaring $text inside your while loop each time and then matching it, which doesn't make sense, and should result in a "Use of uninitialized value in substitution" warning.

    However, it's good practice to avoid global variables when possible. Instead, you can do something like this:

    use strict; use warnings; use Data::Dumper; sub load_file { my $file = shift; my $text; { local $/; open my $fh, $file or die "Can't open $file $!"; $text = <$fh>; } return $text; } my $text = load_file( '/home/greyfox/data/TBLLOTUSNOTESPYRAMID.txt' );

    Then, you can pass $text as a parameter to a subroutine that processes the second file, for example.

      You're also re-declaring $text inside your while loop each time and then matching it, which doesn't make sense, and should result in a "Use of uninitialized value in substitution" warning.
      This is not true. An our-variable is declared only for the current block, but it's the same variable every time you declare it. The following code works fine:
      use strict; use warnings; { our $text = 'test'; } { our $text =~ s/t/T/; } { print our $text; # "Test" }
      However I can't tell why Grey Fox's code doesn't work. He should have provided the input files.
Re: Use of a global scalar
by shmem (Chancellor) on Sep 02, 2006 at 23:58 UTC
    This is a fine moment for
    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

    ;-)

    See our. Variables declared with our aren't global.

    The only global variables in perl are the 'special' variables, e.g. $_. But with these, "global" means only that the symbol is available everywhere, without any previous declaration - but the actual value accessible through that symbol is subject to localizing and aliasing.

    The documentation for our stresses within the current scope - and a block boundary is a scoping boundary.

    Say use vars qw($text) to have a package global, or use ${^_text} to have a really real global (the symbol is bound to the package main, though).

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Cute, but if I read the manual I wouldn't learn such interesting uses of the perl command line. :-)

      -- Grey Fox
      Perl - Hours to learn lifetime to master.
Re: Use of a global scalar
by betterworld (Curate) on Sep 03, 2006 at 02:31 UTC
    our $text =~ s/$data[0]/$data[2]/g;
    You should note that $data[0] is interpreted as a regular expression, which is probably not what you want. This common error is often the cause of vulnerabilities. See "DON'T" in perlcheat and "\Q" in perlre.
      Thank you much;
      It took me a little while to figure out that the regex was using the address instead of the value. I knew it wasn't working but didn't know why. Now I know where to look.
      Thanks, again.

      -- Grey Fox
      Perl - Hours to learn lifetime to master.