http://www.perlmonks.org?node_id=717688

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

Hi to everyone!
I've started playing around with perl just a week ago, and now I've a problem.
I've a text file with a list like this:

word1:word2 word3:word4 word5:word6

and I'd like to import it in a hash (with the left word as a key and the right word as the value) because I need to use them later as two values in a regex.

My code is like this:

open FILE1, "text_file_with_words.txt" or die; my %hash; while (my $line=<FILE1>) { chomp; (my $word1,my $word2) = split /:/, $line; $hash{$word1} = $word2; }

but it doesn't seem to work. And, obviously, I can't understand why.
I hope I haven't make too much mistakes posting. I'm italian, so I'm sorry for my bad English.
I'm looking forward for any helpful suggestion..

Replies are listed 'Best First'.
Re: Putting text file into a hash
by ikegami (Patriarch) on Oct 17, 2008 at 08:37 UTC

    I've started playing around with perl just a week ago

    Some comments unrelated to your question:

    • Avoid using global variables. Use lexical variables for file handles.

      open my $fh, "text_file_with_words.txt" or die; while (my $line = <$fh>) { ... }
    • $! contains an error message when open fails.

    • I prefer to use the three argument form of open. It has fewer possible surprises.

      open(my $fh, '<', $qfn) or die("Can't open input file \"$qfn\": $!\n");
    • (my $var1, my $var2)
      can be written as
      my ($var1, $var2)

Re: Putting text file into a hash
by ikegami (Patriarch) on Oct 17, 2008 at 08:26 UTC

    Tip: Put your code inside <c>...</c> tags when you post it. It preserves the spacing and escapes special characters for you.

    but it doesn't seem to work.

    That's not very helpful. Tell us what it does that is shouldn't do, or what it doesn't do that it should do.

    Your program works as is. The only problem I see is that you are chomping the wrong variable. chomp works on $_ when no argument is specified. Use chomp($line);.

    open FILE1, "text_file_with_words.txt" or die; my %hash; while (my $line=<FILE1>) { chomp($line); (my $word1,my $word2) = split /:/, $line; $hash{$word1} = $word2; } use Data::Dumper; print Dumper \%hash;
    $VAR1 = { 'word1' => 'word2', 'word5' => 'word6', 'word3' => 'word4' };
Re: Putting text file into a hash
by GrandFather (Saint) on Oct 17, 2008 at 08:25 UTC

    Define "doesn't seem to work". If you change the chomp line to chomp $line; then the code works as I would expect.

    For sample code adding sample data in a __DATA__ section after your code and using <DATA> for your file handle makes it easier for us to reproduce your problem.


    Perl reduces RSI - it saves typing
Re: Putting text file into a hash
by heth (Sexton) on Oct 17, 2008 at 08:30 UTC

    hi,

    You're pretty good after one week of perling :-)

    Try this code

    # Using inline DATA instead of file for testing. #open FILE1, "text_file_with_words.txt" or die; my %hash; while (my $line=<DATA>) { chomp $line; print $line,"\n"; (my $word1,my $word2) = split /:/, $line; $hash{$word1} = $word2; } # Print hash for testinf purposes while ( my ($k,$v) = each %hash ) { print "Key $k => $v\n"; } __DATA__ word1:word2 word3:word4 word5:word6

    Good luck Perler

Re: Putting text file into a hash
by binf-jw (Monk) on Oct 17, 2008 at 09:04 UTC
    Personally I write your code like this:
    use English '-no_match_vars'; open $input_fh, '<', $input_fn or die 'Could not open file: ', $OS_ERR +OR; my $hash; while ( my $line = <$input_fh> ) { chomp $line; last if ! $line; # Split line with a limit of two my ( $word1 , $word2 ) = split /:/, $line, 2; $hash->{$word1} = $word2; } close $input_fh or die 'Could not close file: $OS_ERROR';

    Alot of coding practices are personal preference but there are some good guidelines to follow.
    I would say always use lexical variable for file handles. You can assign a lexical fh by opening as i've done or by using the glob from the symbol table like this:
    my $output = *STDOUT;
    Then you can even pass it via subroutines to assign handles:
    ## This in a package else where ## 'inside-out obj' sub assign_log_handle { my $self = shift; $log_handle->{$self} = shift; return; } ## From main code Your::Package->assign_log_handle( *STDERR );
    Update: Just seen ikegami has already got there with this, But oh well. note: $OS_ERROR is the same as the $! that he mentioned.
    Update: added: '-no_match_vars' :P John
        Yep use English '-no_match_vars' Have added it now.
Re: Putting text file into a hash
by remluvr (Sexton) on Oct 17, 2008 at 09:25 UTC
    Thanks everyone, now it works just fine. I'm really thankful for all your help and suggestion and I'm trying to use every suggestion you gave me to make my code better. So, thanks again.
Re: Putting text file into a hash
by remluvr (Sexton) on Oct 17, 2008 at 08:55 UTC
    Thanks everyone, I'm working on it and I hope I can make it work.
    Every suggestion was very helpful, even the one unrelated to my question. As I said I'm pretty new to Perl, so I need to learn almost everything.
    Thanks again.
      Always use strict and warnings which will make your life easier and also speed up your
      learning and development process. Use of warnings would have alert you about the chomping of
      wrong variable in your code.

      I personally believe that you're still failing to specify how is it failing to "work." Because by all means it should! That is, it should if the input file you're running your code is actually as regular as you suggested. If it isn't, then you may run into troubles. Incidentally I've just answered a question which is virtually the same as yours except that the code of the person asking it is some orders of magnitude worse than yours! (Which is a way to say: compliments for your programming skills after only a week of Perl programming!) Actually, in the linked post I suggest another technique to achieve the same, which is even more "sensible" to the format of the input file, for a broken record may mess up all of the following keys and values...

      --
      If you can't understand the incipit, then please check the IPB Campaign.
Re: Putting text file into a hash
by Anonymous Monk on Oct 17, 2008 at 18:00 UTC
    my %hash = map {chomp; split ':', $_} <FILE>;
Re: Putting text file into a hash
by Anonymous Monk on Oct 17, 2008 at 19:06 UTC
    Hello,

    I'm no monk at all. Was actually stopping by to post my own question, but I think I can help you here. You can set it by doing this:

    open FILE1, "text_file_with_words.txt" or die;
    %hash = map {chomp; split /:/} (<FILE1>);

    I hope that helps.


    -Sean
    AKA: Morpheous1129
      Aa crap!! Looks like one of the monks already responded with the answer. Sorry then.

      -Sean
      AKA: Morpheous1129
Re: Putting text file into a hash
by Cuhulain (Beadle) on Oct 19, 2008 at 00:08 UTC
    Ciao, remluvr.

    Try loading your program into http://www.perlcritic.com/
    This offers useful advice based on Damian Conway's book Perl Best Practices. It offers 5 levels of severity, from gentle to brutal.

    Better still, if you do not always have a web connection, and are happy using Vim as your editor, try downloading perl-support.vim from http://www.vim.org/scripts/script.php?script_id=556. This includes a Perl menu, with an option to run your code thru perlcritic. And perltidy as well.

    Enjoy.
Re: Putting text file into a hash
by Amron (Initiate) on Oct 17, 2008 at 17:23 UTC
    I think I understand your problem, and here is what I would do: open(FILEHANDLE, "<hash.dat") or die("boo! error"); while(<FILEHANDLE>){ print $_; %hash = split(" ", <FILEHANDLE>); } update: and by the way, sorry for the bad format of the post..... will read up now
      Your code does not work. After reading up on posting (Writeup Formatting Tips), try to run your code.

      When I add use warnings; use strict;, there are warnings which give you a clue as to why it might be failing:

      use strict; use warnings; use Data::Dumper; my %hash; open(FILEHANDLE, "<hash.dat") or die("boo! error"); while(<FILEHANDLE>) { # print $_; %hash = split(" ", <FILEHANDLE>); } print Dumper(\%hash); __END__ Odd number of elements in hash assignment at .., <FILEHANDLE> line 2. $VAR1 = {};
Re: Putting text file into a hash
by remluvr (Sexton) on Oct 20, 2008 at 14:37 UTC
    Again, thanks to everyone! Your suggestions have been so helpful. Now it works as I wanted. Thanks again!
Re: Putting text file into a hash
by Anonymous Monk on Oct 20, 2008 at 16:03 UTC
    to help debug: use warnings; use strict; change (my $word1,my $word2)= split /:/, $line; to my ($word1, $word2)= split /:/, $line;
      One another solution
      perl -MData::Dumper -e 'my ($Key,$Value) = split (/:/) ; $hash{$Key} = + $Value ;END{print Dumper \%hash};' -ln 'filename'
      But the above code will not handle error conditions.