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

Hi,

I have a glossary file containing localizied versions of different words;

e.g.

%current = ( eng => 'Current', ca => 'Courant', de => 'Zur Zeit verfuegbar', fr => "Actuellement", br => 'Atualmente', ar => 'Actual', cl => 'Actual', co => 'Actual', mx => 'Actual', ve => 'Actual', es => 'Actual', ); %or = ( eng => 'or', es => 'o', ar => 'o', cl => 'o', co => 'o', mx => 'o', ve => 'o', br => 'ou', it => 'o', pl => 'lub', );

So $current{"de"} gives you the German representation of the word "current"

I'm looking to create a webpage with a large table showing hash names in the first column then all other columns listing the translated (localizied) version for each country (I have country codes in a seperate hash that I can cycle through)

The Question..

Is there a module or a simple way of listing all the hashes in the file glossary.pl? I would ideally like this information in an array or hash names eg..

@hashNames = [ "current", "or", "the", "revised" ]

Any nice module to parse the file for me?

Thanks people

M

Replies are listed 'Best First'.
Re: Passing hash names in a file
by jdporter (Paladin) on Dec 09, 2002 at 20:24 UTC
    Well clearly it's a bad idea to have variable names which are words in some human language. Instead, have a two-level hash, in which the top-level key is the word. E.g.
    my %trans; # a translation table. $trans{'current'} = { eng => 'Current', ca => 'Courant', . . . };
    Then to get the list of all the words in the glossary, you'd just take the keys of the hash, i.e.     @glossary_words = keys %trans;

    jdporter
    ...porque es dificil estar guapo y blanco.

      True it would be a lot better to impliment it that way but this file is referenced but quite a few scripts that I do not have control over and so I can not change the structure of the data within glossary.pl

      Can you suggest how I could obtain the names of the hashes without changing the strcture of the data?

      Thanks for your comments so far

      M

Re: Passing hash names in a file
by jsprat (Curate) on Dec 09, 2002 at 23:15 UTC
    Update: As jdporter mentioned above, there needs to be another level of abstraction - using the words as the name of each hash is polluting the namespace and asking for trouble.

    That being said, are you already reading this information into a hash? If so, keys is what you need.

    If you aren't already populating a hash with this, something like this should get you started:

    #!/usr/bin/perl use strict; use warnings; my @keys; { my $glossary = 'gloss'; #filename containing the hash package Glossary; do $glossary or die "Error doing $glossary: $!"; @keys = keys %Glossary::; } print join "\n", @keys;

    Note - if the file contains malicious code, it will be executed. If you use this in production, use Safe.pm and rdo to allow only trusted code to execute.

Re: Passing hash names in a file
by graff (Chancellor) on Dec 10, 2002 at 05:33 UTC
    Any nice module to parse the file for me?

    Well, given the other information you've added, it probably won't be so hard to parse the "glossary.pl" file on your own (the following has not been tested):

    open(GLOSSARY, "glossary.pl") or die $!; my $word = ""; my $trans_hash = (); while (<GLOSSARY>) { if ( /\%(\w+)\s*=\s*/ ) { # look for start of hash definition $word = $1; } elsif ( $word ne "" ) { if ( /(\w+)\s*=>\s*([^,])/ ) { # find key => value assignment my ($lang, $trans) = ($1,$2); $trans_hash{$word}{$lang} = $trans; } elsif ( /^\s+\);/ ) { # watch for the end of the definition $word = ""; } } }
    I'm basing this on the assumption that the style and syntax used in the glossary file are tightly constrained (and that the sample you showed is an accurate picture of the style being used). There's no guarantee that people adding to "glossary.pl" will always hew to the specific style shown in your post, but the fact that it's a shared resource makes it more likely that it will always have an easy, predictable format (at least, you could make it so without causing any of the dependent scripts to break.)

    If the glossary file is likely to grow over time, you just need to make sure that it remains consistent with your parsing assumptions -- and maybe add a couple of error checks within or after the parsing loop above, to watch for signs of trouble (e.g., see if some words lack translations for some languages).

    Since you're just reading the glossary.pl script as text data and using its contents to define keys and values for a hash array, this approach doesn't really pose any safety issues.

    update: added a few comments to the code.

Re: Passing hash names in a file
by dingus (Friar) on Dec 10, 2002 at 09:38 UTC
    Assuming the data in your glossary.pl file is as you specify (each hash on a separate line or lines) then you can parse it quite quickly:
    $fn = 'glossary.pl'; $/ = ');'.$/; # cunning trick to read in the whole hash open (FILE, "<$fn"); while (<FILE>) { next unless (/%(\w+)(?:\s|=)/s); # match %word = or %word= push @hashnames, $1; } close(FILE);

    Dingus


    Enter any 47-digit prime number to continue.

      Thanks for everyones suggestions!

      Here's how I solved it in the end.

      while(<MyFile>){ if (/(\%.*?) /){ $item = $1; $item =~ s/\%//; push @dynamicterms, $item } }

      Really wasn't that hard was it!

      Thanks

      M