FAQ
Hello,

Following the suggestion of one of you (sorry, don't remember who's...),
I am skimming through my old Perl scripts and trying to improve them.
Now I have a problem with one of them, after inserting "use strict;" -
would be great, if you could help me:

The script is being started with a parameter $stp (among others) that
can be one of mvb/pkv/av/be/vvw. This parameter is used as a key for a
master hash the values of which are names of other hashes themselves.

# Master-Hash
my %stp_dirs = ( "mvb" => "mvb_dirs",
"pkv" => "pkv_dirs",
"av" => "av_dirs",
"be" => "be_dirs",
"vvw" => "vvw_dirs" );

# AV
my %av_dirs=( "dir11" => "dir12"
"dir13" => "dir14" );

# BE
my %be_dirs=( "dir21" => "dir22"
"dir23" => "dir24" );

# MVB
my %mvb_dirs= ("dir31" => "dir32"
"dir33" => "dir34" );

# PKV
my %pkv_dirs=( "dir41" => "dir42"
"dir43" => "dir44" );

# VVW
my %vvw_dirs=( "dir51" => "dir52"
"dir53" => "dir54" );

Before "use strict;" the replacement of $stp in the hash name below
worked fine

my ($sdir, $tdir);
while (($sdir,$tdir) = each %{$stp_dirs{$stp}}) {
DEBUG("SourceDir: $sdir\t\tTargetDir: $tdir\n");
}

now I get an error:

Can't use string ("mvb_dirs") as a HASH ref while "strict refs" in use
at -e line 148.

Can somebody please point me into the right direction? Also, I'd like to
know whether this is "good practice" - I found something in the infinite
depths of the www that using a variable in a name is a bad idea, but in
this case I do not have any other idea how to accomplish that (at least,
perlcritic.org didn't complain about that).

Thanks in advance,
Nora

Search Discussions

  • Thomas Bätzler at May 12, 2010 at 9:46 am

    HACKER Nora wrote:
    The script is being started with a parameter $stp (among others) that
    can be one of mvb/pkv/av/be/vvw. This parameter is used as a key for a
    master hash the values of which are names of other hashes themselves.

    # Master-Hash
    my %stp_dirs = ( "mvb" => "mvb_dirs",
    "pkv" => "pkv_dirs",
    "av" => "av_dirs",
    "be" => "be_dirs",
    "vvw" => "vvw_dirs" );

    # AV
    my %av_dirs=( "dir11" => "dir12"
    "dir13" => "dir14" );

    # BE
    my %be_dirs=( "dir21" => "dir22"
    "dir23" => "dir24" );

    # MVB
    my %mvb_dirs= ("dir31" => "dir32"
    "dir33" => "dir34" );

    # PKV
    my %pkv_dirs=( "dir41" => "dir42"
    "dir43" => "dir44" );

    # VVW
    my %vvw_dirs=( "dir51" => "dir52"
    "dir53" => "dir54" );
    Try:

    #!/usr/bin/perl -w

    use strict;

    # AV
    my %av_dirs=( 'dir11' => 'dir12',
    'dir13' => 'dir14' );

    # BE
    my %be_dirs=( 'dir21' => 'dir22',
    'dir23' => 'dir24' );

    # MVB
    my %mvb_dirs= ('dir31' => 'dir32',
    'dir33' => 'dir34' );

    # PKV
    my %pkv_dirs=( 'dir41' => 'dir42',
    'dir43' => 'dir44' );

    # VVW
    my %vvw_dirs=( 'dir51' => 'dir52',
    'dir53' => 'dir54' );

    my %stp_dirs = ( 'mvb' => \%mvb_dirs,
    'pkv' => \%pkv_dirs,
    'av' => \%av_dirs,
    'be' => \%be_dirs,
    'vvw' => \%vvw_dirs );

    while ( my($sdir,$tdir) = each %{$stp_dirs{'mvb'}}) {
    print("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }

    __END__

    HTH,
    Thomas
  • HACKER Nora at May 12, 2010 at 10:12 am
    Hi Thomas,
    Try:

    my %stp_dirs = ( 'mvb' => \%mvb_dirs,
    'pkv' => \%pkv_dirs,
    'av' => \%av_dirs,
    'be' => \%be_dirs,
    'vvw' => \%vvw_dirs );

    while ( my($sdir,$tdir) = each %{$stp_dirs{'mvb'}}) {
    print("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }
    Is that 'mvb' intentional? Also, I don't understand why to put '\%' in front of the values from the master hash. Nevertheless, I tried the alterations as suggested but the error remains:

    Can't use string ("%mvb_dirs") as a HASH ref while "strict refs" in use at /opt/data/magna/wartung/tools/get_lieferung.pl line 145.

    Any other hints?

    Kind regards,
    Nora
  • Thomas Bätzler at May 12, 2010 at 10:28 am

    HACKER Nora asked:
    Try:

    my %stp_dirs = ( 'mvb' => \%mvb_dirs,
    'pkv' => \%pkv_dirs,
    'av' => \%av_dirs,
    'be' => \%be_dirs,
    'vvw' => \%vvw_dirs );

    while ( my($sdir,$tdir) = each %{$stp_dirs{'mvb'}}) {
    print("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }
    Is that 'mvb' intentional? Also, I don't understand why to put '\%' in
    front of the values from the master hash. Nevertheless, I tried the
    alterations as suggested but the error remains:

    Can't use string ("%mvb_dirs") as a HASH ref while "strict refs" in use
    at /opt/data/magna/wartung/tools/get_lieferung.pl line 145.
    If you "use strict;" you may not use symbolic references, i.e. (mis)use a variable's name to create a reference to it. That's why I fixed your code
    by replacing the variable names with references to the variable I assumed you'd wish to address.

    Maybe you should take a look at the perlref manpage (e.g. http://perldoc.perl.org/perlref.html) for a better explanation.

    As for putting in a literal 'mvb' that was just to demonstrate the usage. Of course you can replace that with any expression evaluating to any key of %stp_dirs or whatever.

    HTH,
    Thomas
  • HACKER Nora at May 12, 2010 at 10:36 am
    Hi Thomas,
    If you "use strict;" you may not use symbolic references, i.e. (mis)use
    a variable's name to create a reference to it. That's why I fixed your
    code
    by replacing the variable names with references to the variable I
    assumed you'd wish to address.

    Maybe you should take a look at the perlref manpage (e.g.
    http://perldoc.perl.org/perlref.html) for a better explanation.

    As for putting in a literal 'mvb' that was just to demonstrate the
    usage. Of course you can replace that with any expression evaluating to
    any key of %stp_dirs or whatever.
    Thanks for your explanation and the reference to perldoc, I understand now. But it doesn't work yet, I still get the same error. I have altered my source now as follows:

    my %stp_dirs = ( "mvb" => "\%mvb_dirs",
    "pkv" => "\%pkv_dirs",
    "av" => "\%av_dirs",
    "be" => "\%be_dirs",
    "vvw" => "\%vvw_dirs" );
    [...]
    my ($sdir, $tdir);
    while (($sdir,$tdir) = each %{$stp_dirs{$stp}}) {
    DEBUG("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }

    Did I misunderstand anything?

    Cheers,
    Nora
  • Akhthar Parvez K at May 12, 2010 at 10:45 am

    On Wednesday 12 May 2010, HACKER Nora wrote:
    Thanks for your explanation and the reference to perldoc, I understand now. But it doesn't work yet, I still get the same error. I have altered my source now as follows:

    my %stp_dirs = ( "mvb" => "\%mvb_dirs",
    "pkv" => "\%pkv_dirs",
    "av" => "\%av_dirs",
    "be" => "\%be_dirs",
    "vvw" => "\%vvw_dirs" );
    Remove the quotes. When you put something around quotes, you're telling it's a string and a reference is not a string as you know.

    --
    Regards,
    Akhthar Parvez K
    http://Tips.SysAdminGUIDE.COM
    UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity - Dennie Richie
  • Thomas Bätzler at May 12, 2010 at 10:49 am

    HACKER Nora asked:
    Thanks for your explanation and the reference to perldoc, I understand
    now. But it doesn't work yet, I still get the same error. I have
    altered my source now as follows:

    my %stp_dirs = ( "mvb" => "\%mvb_dirs",
    "pkv" => "\%pkv_dirs",
    "av" => "\%av_dirs",
    "be" => "\%be_dirs",
    "vvw" => "\%vvw_dirs" );
    [...]
    my ($sdir, $tdir);
    while (($sdir,$tdir) = each %{$stp_dirs{$stp}}) {
    DEBUG("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }

    Did I misunderstand anything?
    Yes, you're using double quotes around the hash references.

    Note how I wrote it:

    my %stp_dirs = ( 'mvb' => \%mvb_dirs,
    'pkv' => \%pkv_dirs,
    'av' => \%av_dirs,
    'be' => \%be_dirs,
    'vvw' => \%vvw_dirs );

    Cheers,
    Thomas
  • Akhthar Parvez K at May 12, 2010 at 10:40 am
    Hi Nora,
    On Wednesday 12 May 2010, HACKER Nora wrote:
    while ( my($sdir,$tdir) = each %{$stp_dirs{'mvb'}}) {
    print("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }
    Is that 'mvb' intentional? Also, I don't understand why to put '\%' in front of the values from the master hash. Nevertheless, I tried the alterations as suggested but the error remains:

    Can't use string ("%mvb_dirs") as a HASH ref while "strict refs" in use at /opt/data/magna/wartung/tools/get_lieferung.pl line 145.

    Any other hints?

    Kind regards,
    Nora
    You put an escape character '\' (no quote) to point to another hash (what follows / symbol, to be more precise). It's known as (hash/array/code) references.

    my %stp_dirs = ( 'mvb' => \%mvb_dirs,
    'pkv' => \%pkv_dirs,
    'av' => \%av_dirs,
    'be' => \%be_dirs,
    'vvw' => \%vvw_dirs );

    Here, value for the key 'mvb' in the hash %stp_dirs is a reference to another hash (%mvb_dirs) and that's what the beauty with references as you can build a *big* data structure. Thomas took 'mvb' just for an example and his code should work fine. I've modified it a bit to get what exactly you wanted:

    #!/usr/bin/perl
    use strict;
    use warnings;

    # AV
    my %av_dirs = ( "dir11" => "dir12", "dir13" => "dir14" );
    # BE
    my %be_dirs=( "dir21" => "dir22", "dir23" => "dir24" );
    # MVB
    my %mvb_dirs= ("dir31" => "dir32", "dir33" => "dir34" );
    # PKV
    my %pkv_dirs=( "dir41" => "dir42", "dir43" => "dir44" );
    # VVW
    my %vvw_dirs=( "dir51" => "dir52", "dir53" => "dir54" );
    # Master-Hash
    my %stp_dirs = ( "mvb" => \%mvb_dirs,
    "pkv" => \%pkv_dirs,
    "av" => \%av_dirs,
    "be" => \%be_dirs,
    "vvw" => \%vvw_dirs );
    foreach my $sub_hash (keys %stp_dirs)
    {
    print 'Contents from %' . "$sub_hash\n";
    while (my ($sdir,$tdir) = each %{$stp_dirs{$sub_hash}})
    {
    print ("SourceDir: $sdir\t\tTargetDir: $tdir\n");
    }
    }


    --
    Regards,
    Akhthar Parvez K
    http://Tips.SysAdminGUIDE.COM
    UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity - Dennie Richie
  • HACKER Nora at May 12, 2010 at 10:53 am
    Hi,
    You put an escape character '\' (no quote) to point to another hash
    (what follows / symbol, to be more precise). It's known as
    (hash/array/code) references.

    my %stp_dirs = ( 'mvb' => \%mvb_dirs,
    'pkv' => \%pkv_dirs,
    'av' => \%av_dirs,
    'be' => \%be_dirs,
    'vvw' => \%vvw_dirs );
    Thank you so much! I thought I understood - but did not really,
    obviously :-/ It works now, after removing the double quotes.

    Kind regards,
    Nora

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedMay 12, '10 at 9:33a
activeMay 12, '10 at 10:53a
posts9
users3
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase