0

I have a txt file like this
$CHUNK_QTY = "50000";
$CLIENT = "hi all";
$CLIENT_CODE = "NMB";
$COMPOSER = "DIALOGUE";
$CONTROL_FILE_NAME = "NMBM725.XML";
$COPY_BASE = "01";
$CSITE = "NSH";
$DATA_TYPE = "MET";
$DIALOGUE_VERSION = "V7R0M624";
$DISABLE = "N";
$DPI = "300";
$DP_BAR_START = "A";
$DP_BAR_STOP = "Z";
$DUPLEX = "N";
$Dialogue_Version = "V7R0M624";
$EMAIL_ERROR = "Y";
$EMAIL_ON = "N";

I have many variables up to 500. I would like to access value for corresponding variable. For example if I want to access $DPI it should print 300 . How do I do that in perl. Any help will be appreciated. I would like something different than regex.

Thanks

4 Answers 4

2

Incorrect, wrong, bad, and dangerous way:

eval qx{cat filename.txt};
print "$DPI\n";

or

do "filename.txt";
print "$DPI\n";

so don't do it.

It is much better parse and untaint the file for example with regex...

If not want regex based solution, you at least can use the Safe.pm module:

use Safe;
my $sandbox = new Safe;
$sandbox->rdo( "filename.txt"  ) or die "safe problem $@";

#more safe now
do "filename.txt";
print "$DPI\n";

the rdo is like do but in safe environment, especially it can catch the $X = qx {rm -rf /}; constructions. If the file passed the rdo it probably can be do-ed.

Of course, the above is wrong too, because you cannot use use strict; as TLP already told. The best way is parsing the file.

And for regex based solution you can use:

use strict;
use warnings;
my $re = qr /^\s*\$(\w+)\s*=\s*"(.*)"\s*;\s*$/o;
my %conf = map { m/$re/;($1,$2) } grep {$re} <DATA>;
__END__
$CHUNK_QTY = "50000";
$CLIENT = "hi all";
$CLIENT_CODE = "NMB";
$COMPOSER = "DIALOGUE";
$CONTROL_FILE_NAME = "NMBM725.XML";
$COPY_BASE = "01";
$CSITE = "NSH";
$DATA_TYPE = "MET";
$DIALOGUE_VERSION = "V7R0M624";
$DISABLE = "N";
$DPI = "300";
$DP_BAR_START = "A";
$DP_BAR_STOP = "Z";
$DUPLEX = "N";
$Dialogue_Version = "V7R0M624";
$EMAIL_ERROR = "Y";
$EMAIL_ON = "N";
Sign up to request clarification or add additional context in comments.

4 Comments

Maybe you could give a brief example of the preferred way to do it; you've written four lines of code showing how not to do it, and zero showing an alternative.
See, he explicitly exclude regex based solution. Using do is extremely dangerous, for example when the file contains $C = qx { rm -rf /}; Parsing the file could be easy or hard... depends. But feel free and write the correct way. Im novice here, so thanks for your comment.
Thanks novacik. I thould like there could be some library or something so that I can access variables.
If absolutely can trust to input, you can use the "do filename" method. For some added safety - see the edited answer.
1

You can use do for a file to run it:

do "yourfile";
print $DPI;

However, if you are running under use strict, as you should, you'd need to first declare the variables with our:

use strict;
use warnings;

our $DPI; # plus any other variables you want to use
do "yourfile";
print $DPI;

1 Comment

@user1515661 You should be aware that do actually executes the file, so if you have reason not to trust the file's content, you should not execute it. There are better ways to store and retrieve data.
1

You could use hashes, that way you could write the names and values into the hash list and retrieve them based on their names.

Here is a method to read the contents of a file and put the contents into the hash structure:

my $hash = ();
open FILE, "<", "stuff.txt" or die $!;

while(<FILE>)
{
    my @attr  = split(/=/);
    #this is actually a regexp, but you can read the data in any way you want

    my $key   = $attr[0];
    my $value = $attr[1];
    #only splitting up so that it becomes easier to read

    $hash{$key} = $value;#insert key and value  
}
close (FILE);
print 'Content of $CLIENT:'.$hash{'$CLIENT'};
print 'Content of $CHUNK_QTY:'.$hash{'$CHUNK_QTY'};

Contents of the file "stuff.txt"

$CLIENT="hi all"
$CHUNK_QTY="50000"

2 Comments

But I already have the file described above. So I want to access variable how can I do that using hash.
You have to fill in the variables into the hash, I have edited my post.
0

Here's a quick example showing how to take lines in the format that you gave above and put them into a hash:

#!/usr/bin/env perl    

use strict;
use warnings;

my %vars;
while (my $line = <DATA>) {
  chomp $line;          # remove linebreak
  $line =~ s/^\$//;     # Optional: remove $ from start of variable name

  my ($key, $value) = $line =~ /^(\w+)\s*=\s*(.*)$/;
  $value =~ s/;$//;     # Remove trailing semicolon
  $value =~ s/^"//;     # Remove leading double-quotes
  $value =~ s/"$//;     # Remove trailing double-quotes
  $vars{$key} = $value;
} 

for my $key (sort keys %vars) {
  print "$key has value $vars{$key}\n";
}

print "CLIENT says $vars{CLIENT}\n";

__DATA__
$CHUNK_QTY = "50000";
$CLIENT = "hi all";
$CLIENT_CODE = "NMB";
$COMPOSER = "DIALOGUE";
$CONTROL_FILE_NAME = "NMBM725.XML";
$COPY_BASE = "01";
$CSITE = "NSH";
$DATA_TYPE = "MET";
$DIALOGUE_VERSION = "V7R0M624";
$DISABLE = "N";
$DPI = "300";
$DP_BAR_START = "A";
$DP_BAR_STOP = "Z";
$DUPLEX = "N";
$Dialogue_Version = "V7R0M624";
$EMAIL_ERROR = "Y";
$EMAIL_ON = "N";

There should be enough here to get you started, but you'll need to read up on how to open an actual file (instead of using the __DATA__ section as I did here) for yourself. I recommend checking perldoc open for examples and full details.

1 Comment

Thank you very much Dave, I think it should be great help. Wow, stackoverflow rocks and you too Dave.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.