Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

find values in a file

Status
Not open for further replies.

donny750

Programmer
Joined
Jul 13, 2006
Messages
145
Location
FR
hello,

Somebody can help,look me where i must look information for doing this :

I've file
values.txt
#------------------
#Important
#------------------

export scan=YES
export vinils=/home/vinils
export dayof=NO

#------------------
#sub
#------------------

export var1=easy
export var2=medium
export var3=hard

and i want to recover the values of the variables
in the best world i want to take him in a array like this
Code:
%values ("scan" => "YES",
"vinils" => "/home/vinils",
"dayof" => "NO",
....
"var3" => "hard"
);

it's possible ?

thanks
 
Code:
use strict;
use warnings;

my %values;

while (<DATA>) {
   chomp;
   next if (/^\s*$/);
   next if (/^\s*#/);
   my ($name, $value) = split(/=/, $_);
   $values{$name} = $value;
}

foreach (sort keys %values) {
   print "$_: $values{$_}\n";
}

__DATA__


#------------------
#Important
#------------------

export scan=YES
export vinils=/home/vinils
export dayof=NO

#------------------
#sub
#------------------

export var1=easy
export var2=medium
export var3=hard
Untested, as I don't have a machine with perl here. You'd probably use a separate file though. It's such a common requirement that I'd be surprised if there wasn't a module on CPAN to do it...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
thanks
i've add this to the script
Code:
#!/usr/bin/perl

use strict;
use warnings;

my %values;
my $infile = 'input.txt';
open DATA, $infile or die $!;

while (<DATA>) {
   chomp;
   next if (/^\s*$/);
   next if (/^\s*#/);
   my ($name, $value) = split(/=/, $_);
   $values{$name} = $value;
}

foreach (sort keys %values) {
   print "$_: $values{$_}\n";
}

in ouptut i've this
export dayof: NO
export scan: YES
export var1: easy
export var2: medium
export var3: hard
export vinils: /home/vinils

it is possible to have just this
dayof: NO
scan: YES
var1: easy
var2: medium
var3: hard
vinils: /home/vinils

??
 
Add the following line
Code:
   my ($name, $value) = split(/=/, $_);
   [red]$name =~ s/^\s*export\s+(\w+)/$1/;[/red]
   $values{$name} = $value;
which ought to do it.


Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
thanks steve
it's run well
know i must understand your code
and continu to find a good web site who explain regex for understanding your script
and doing another script with regex if later i need to do another script with different condition

 
donny

Here's an explanation
Code:
#!/usr/bin/perl

use strict;
use warnings;

my %values;
my $infile = 'input.txt';
open DATA, $infile or die $!;

while (<DATA>) {
   [gray]# remove trailing linefeed[/gray]
   chomp;

   [gray]# ignore lines containing only zero-to-many spaces[/gray]              
   next if (/^\s*$/);

   [gray]# ignore comment lines[/gray]
   next if (/^\s*#/);

   [gray]# split on the equals sign[/gray]
   my ($name, $value) = split(/=/, $_);

   [gray]# edit the $name - the (\w+) captures the bit
   # we want as $1, then replaces $name with $1[/gray]
   $name =~ s/^\s*export\s+(\w+)/$1/;

   [gray]# add the name-value pair to the hash[/gray]
   $values{$name} = $value;
}

foreach (sort keys %values) {
   print "$_: $values{$_}\n";
}
HTH

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
thanks steve

in another file i've built a another script and in this script i've the array
my script
Code:
our @myvar = 
( 
"dayof" => "YES",
"scan" => "NO",
"var1" => "NOeasy",
"var2" => "Nomedium",
"var3" => "Nohard"
"vinils" => "/home1/novinils"
);

and i'want when i find the values in the first file
modify the second file with the values i've take in the first file;

for example,in the first file dayof = NO
i want modify the second file with NO;

firstly, i've try to find the values (for example YES for the dayof) in the second file and replace him by the new value;

i've try this
Code:
#!/usr/bin/perl

use strict;
use warnings;

#my %values;
my $infile = 'output.txt';

open DATA, $infile or die $!;

while (<DATA>) {
   chomp;
   
   next if (/^\s*$/);
   next if (/^\s*#/);
   my ($name, $value) = split(/=/, $_);
   $name =~ s/^\s*\w+\s*=>\s+(\w+)/$1/;
   
   print $name."\n";
   
}

in output i've this
our @myvar
(
"dayof"
"scan"
"var1"
"var2"
"var3"
"vinils"
);
 
Print your $name and $value before substitution, i.e
Code:
...
   print "\$name=$name\n";
   print "\$value=$value\n";
   $name =~ s/^\s*\w+\s*=>\s+(\w+)$/$1/;
...
Then by runnig of this script you will obtain that
Code:
...
$name="dayof"
$value=> "YES",
"dayof"
$name="scan"
$value=> "NO",
...
So, you see, that your regular expresion will never match $name, e.g it will not find the characters '=>' in your $name
 
donny750,

you have:

Code:
our @myvar =
(
"dayof" => "YES",
"scan" => "NO",
"var1" => "NOeasy",
"var2" => "Nomedium",
"var3" => "Nohard",
"vinils" => "/home1/novinils"
);

but you probably want:

Code:
our %myvar =
(
"dayof" => "YES",
"scan" => "NO",
"var1" => "NOeasy",
"var2" => "Nomedium",
"var3" => "Nohard",
"vinils" => "/home1/novinils"
);

- Kevin, perl coder unexceptional!
 
thanks
just one thing i don't understand
why when i print the values taken from my input file , these values are not in the same order in the input file ??

values in the input file :
scan=YES
vinils=/home/vinils
dayof=NO
var1=easy
var2=medium
var3=hard

printing values from the array:
dayof= NO
scan= YES
var1=easy
var2=medium
var3=hard
vinils=/home/vinils
 
The order of keys in a hash is undefined. If you want them ordered, use sort.

Looking back at this thread, it looks like you are editing one script with another. This is generally a bad idea. Keep the data and the code in separate files.

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
i've found
i create a table with 2 dimensions
Code:
my @v = ();
open DATA, $infile or die $!;
while (<DATA>) {
   chomp;
   next if (/^\s*$/);
   next if (/^\s*#/);
   my ($name, $value) = split(/=/, $_);
   $name =~ s/^\s*export\s+(\w+)/$1/;
 push (@v,[$name,$value]);
}
 
But then you have an array of references at an array and it would be a little bit comlicated if you want obtain it's elements e.g.:
Code:
$range = @v;
print "$range\n";

for ($j=0; $j < $range; $j++){
  print "\$j=$j, @v[$j]->[1] => @v[$j]->[1]\n";
}
 
donny750,
I don't understand why you want with a separate Perl-script change the value of hash %myvar in another Perl-script and this want you do by using of array of references, when it could be done on the simpler way.

You have given the file input.txt, from which you want parse the vars/vals for settings and in the another file you have the Perl-Script - e.g. values.pl - which contains the hash %myvar and you want to set %myvar that it corresponds to your file input.txt.

You need only to take the stevexff's code and include it in your values.pl

I would do it at this way:

1) I would create a simple script val_parse.pl, which contain's the subroutine
Code:
# Script: val_parse.pl
use strict;
use warnings;


sub parse_values {
  ### stevexff's cool subroutine
  
  # store file name in $infile
  my ($infile) = @_;
  my %values;

  open DATA, $infile or die $!;

  while (<DATA>) {
    # remove trailing linefeed
    chomp;
    
    # ignore lines containing only zero-to-many spaces              
    next if (/^\s*$/);
    # ignore comment lines
    next if (/^\s*#/);

    # split on the equals sign
    my ($name, $value) = split(/=/, $_);

    # edit the $name - the (\w+) captures the bit
    # we want as $1, then replaces $name with $1
    $name =~ s/^\s*export\s+(\w+)/$1/;

    # add the name-value pair to the hash
    $values{$name} = $value;
  }
  return %values;
}

# return True-Value
1;

2. Then I would modify my values.pl script that it
a) requires (includes) the script val_parse.pl
b) calls function parse_values and modifies original hash %myvar to new settings.
Here you have a simple example
Code:
# Script: values.pl
our %myvar =
(
"dayof" => "YES",
"scan" => "NO",
"var1" => "NOeasy",
"var2" => "Nomedium",
"var3" => "Nohard",
"vinils" => "/home1/novinils"
);

print "Original hash \%myvar : \n";
foreach (sort keys %myvar) {
   print "$_: $myvar{$_}\n";
}

# load script val_parse.pl
require 'val_parse.pl';
# parse values from input.txt and store them in hash %myvar
our %myvar = &parse_values('input.txt');

print "New hash \%myvar      : \n";
foreach (sort keys %myvar) {
   print "$_: $myvar{$_}\n";
}

The other way would be to create a Perl-Module val_parse.pm which would containt above stevexff's function.
 
thanks it's very interresting
i've modify my script and replace the hash with a array of array
because when i print the variable from my hash ,
the variable are not printing like the order they have been taken in the input fie.
 
donny

As previously noted, hashes are designed for fast lookup of name-value pairs, like a dictionary. In order to achieve this speed, one of the trade-offs is that the order you put them in isn't necessarily the order they come out. For example, say you had a pair of arrays, each with ten thousand values. Array A holds the key, and array B holds the corresponding values. In order to look up the value for a given key, on average you'd have to compare five thousand array values from A (not found is the worst case - you inspect all 10,000 entries only to find you don't have it) before returning the corresponding value from B.

Hashes work differently, using a kind of indexing mechanism. The simplified logic goes 'if I have a key of X, then it must be stored here or it means I don't have it.

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
donny750,

if you want you can sort the hash yusing sort-function as I showed you above
 
thanks
i know i can't sort him
like in script above
but i don't want do sort him
i juste want to have the varibale in the same order they are taken in the input file;

for example
if in my input file i've this
a=1
b=2
h=8
c=9

if i parse the file and take the variable in a hash
and i print the variable i've this

h=8
c=9
b=2
a=1

if i use the sort option i've this
a=1
b=2
c=9
h=8

it's impossible to have the same order like in the input file.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top