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

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

$VAR1 = { '' => '', '362520' => 'Fktn and Name: fukutin[Rattus norvegicus]', '375790' => 'AGRN and Name: agrin[Homo sapiens]', '3339' => 'HSPG2 and Name: heparan sulfate proteoglycan 2[Ho +mo sapiens]', '1428' => 'CRYM and Name: crystallin, mu[Homo sapiens]', }

I am very new at this so help would be appreciated I have a file containing text like the one above, I have called it dumpparse.txt, that I created parsing a bigger file using Data::Dumper module. I want to very siimply change the lead text from $VAR1 to my %hash. Then I can read the file back in and do a hash search. so far I have read in the file as an array and the idea is to just use a simple substitution useing the code like the following. The trouble is the regex and the substitution look like variables and the programme compalins, help would be apreciated. Thanks

# #!/usr/bin/perl; use strict; use warnings; my $hashfile = 'dumpparse.txt'; unless ( open(DUMPPARSE, $hashfile) ) { print "Could not open file $hashfile!\n"; exit; } my @hashfile = <DUMPPARSE>; foreach my $line (@hashfile){ if ($line = ~s/ $VAR1/ my %hash /) } # Close the file. close DUMPPARSE; exit;

Replies are listed 'Best First'.
Re: trouble with substitution
by ww (Archbishop) on Jan 19, 2012 at 03:27 UTC
    "the programme compalins" (sic)
    . Yes, it certainly does. Did you try to understand the complaints?
    C:\>perl -c F:\_Perl_\pl_test\verbatim.pl Global symbol "$VAR1" requires explicit package name at verbatim.pl li +ne 24. syntax error at verbatim.pl line 25, near ") }" verbatim.pl had compilation errors.

    Did you read even the very first section of the posting guidelines (How do I post a question effectively?, inter alia) which tell you'll we'll be better able to help if you tell us (inside code tags) the wording (verbatim!) of what the program says when it "compalins?"

    In any case, the first message says you failed to declare $VAR1 before using it.

    The second points to the fact that you've written an if clause (a "conditional") without a block of code telling the program what to do when the if returns 'true' (and preferably, also, when it returns 'false'). See "Conditionals" in perldoc perlintro (at your CLI) or perlintro (in your browser).

    What you seem to be looking for is something like this:

    #!/usr/bin/perl; use strict; use warnings; use 5.012; my ($line, @newarr); my @hashfile = <DATA>; for my $line (@hashfile){ $line =~ tr/\$//; if ( $line =~ /VAR1/ ) { $line =~ s/VAR1/my \%hash/; push @newarr, $line; } else { push @newarr, $line; } } for $_( @newarr) { say $_; } __DATA__ $VAR1 = { '' => '', '362520' => 'Fktn and Name: fukutin[Rattus norvegicus]', '375790' => 'AGRN and Name: agrin[Homo sapiens]', '3339' => 'HSPG2 and Name: heparan sulfate proteoglycan 2[Ho +mo sapiens]', '1428' => 'CRYM and Name: crystallin, mu[Homo sapiens]', }

    which produces this output:

    $my %hash = { '' => '', '362520' => 'Fktn and Name: fukutin[Rattus norvegicus]', '375790' => 'AGRN and Name: agrin[Homo sapiens]', '3339' => 'HSPG2 and Name: heparan sulfate proteoglycan 2[Ho +mo sapiens]', '1428' => 'CRYM and Name: crystallin, mu[Homo sapiens]', }

    Adding the necessary code to write a new file from @newarr (or, to write the new file without resort to that extra varaible/data structure) is left as an exercise.

    HOWEVER, the job sequence of which this is a part would probably be less subject to error and easier to maintain, were you to process whatever the source data that's fed into your dumpparse.txt into an appropriate data structure (which may or may not be a hash; more likely, not, from the looks of it, but you haven't told us enough to put much credence in that interpretation) and perform the remaining processing in a single script.

    Updated: minor edits for brevity/clarity.

      Thanks for reply. I will look through this. Currently it is all a very steep learning curve, so will take while to understand what you have suggested.

      Thanks again

      bye

Re: trouble with substitution
by kejohm (Hermit) on Jan 19, 2012 at 02:45 UTC

    The $ in the regex needs to be escaped (like this: s/ \$VAR1/ my %hash /) so Perl doesn't go looking for a variable named $VAR1 and complain when it can't find it.

    Also, you have a subtle error in your code. The line if ($line = ~s/ \$VAR1/ my %hash /) is actually performing the search and replace on the default variable $_ (which hasn't been set to anything), taking the bitwise negation of the result (the number of replacements made, most likely zero) and assigning that result to the $line variable, which will most likely be true and execute the if block. The code should be like this:

    ... if ( $line =~ s/ \$VAR1/ my %hash / ) { ... } ...

    In any case, this won't change your input file. You would need to write out to a new file after the search and replace.

    A better way to do this is to specify the name of the variable when you dump your data structure using the $Data::Dumper::Varname variable, eg:

    my %hash = (...); $Data::Dumper::Varname = 'hash'; print Dumper(\%hash);

    An alternative is to use the object-oriented interface. You can specify your own names for your data structures, eg:

    my %hash = (...); print Data::Dumper->Dump( [\%hash], ['hash'] );

    See the docs for Data::Dumper for more details.

    As an aside, you may want to consider dumping your data in a format such as XML or JSON, instead of as a Perl data structure.

    Update: Minor clarifications re syntax.

Re: trouble with substitution
by CountZero (Bishop) on Jan 19, 2012 at 07:28 UTC
    Assuming your dumpparse.txt file contains a straight copy of the output of Data::Dumper), you can simply eval the contents of that file.
    use Modern::Perl; my $data; my $VAR1; my %hash; { local $/; $data = <DATA>; } eval $data; %hash = %$VAR1; __DATA__ $VAR1 = { '' => '', '362520' => 'Fktn and Name: fukutin[Rattus norvegicus]', '375790' => 'AGRN and Name: agrin[Homo sapiens]', '3339' => 'HSPG2 and Name: heparan sulfate proteoglycan 2[Homo sap +iens]', '1428' => 'CRYM and Name: crystallin, mu[Homo sapiens]', }
    Update: Silly me. I totally forgot about the do function!
    use Modern::Perl; my %hash = %{do 'dumpparse.txt'}; say map {"$_ : $hash{$_}\n"} keys %hash;

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      I usually use 'require' to thaw dumped text.

      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $dat = require "dump.txt";

      It has been very handy for me.

        Yes, that will work as well, provided your file lives somewhere @INC points to.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: trouble with substitution
by InfiniteSilence (Curate) on Jan 19, 2012 at 04:04 UTC
    perl -e 'my %hash=(q|a|=>100,q|b|=>300); use Data::Dumper; my $obj = D +ata::Dumper->new([\%hash],[qw|foo|]); print $obj->Dump();' $foo = { 'a' => 100, 'b' => 300

    Maybe stop putting $VAR in the output in the first place?

    Celebrate Intellectual Diversity