CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
need to save the contents of the file in to a hash

 



just_in
New User

Jan 13, 2012, 10:14 PM

Post #1 of 7 (1180 views)
need to save the contents of the file in to a hash Can't Post

Hi,

I have the nagios status.dat file in the following format and i need to get the following fields from the file.

host_name=<xxxxx>
current_state=<0/1>
notifications_enabled=<0/1>

my status.dat file is

service {
host_name=abc.example.com
service_description=apache
modified_attributes=1
event_handler=
has_been_checked=1
should_be_scheduled=0
check_execution_time=0.000
check_latency=2.185
check_type=1
current_state=0
last_hard_state=0
current_attempt=1
max_attempts=1
state_type=1
last_state_change=1325885646
last_hard_state_change=1325885646
last_time_ok=1326369246
last_time_warning=0
last_time_unknown=1325884940
last_time_critical=0
plugin_output=No logs found
performance_data=
last_check=1326369246
next_check=0
current_notification_number=0
last_notification=0
next_notification=0
no_more_notifications=0
notifications_enabled=0
active_checks_enabled=0
passive_checks_enabled=1
event_handler_enabled=1
problem_has_been_acknowledged=0
acknowledgement_type=0
flap_detection_enabled=1
failure_prediction_enabled=1
process_performance_data=1
obsess_over_service=1
last_update=1326369323
is_flapping=0
percent_state_change=0.00
scheduled_downtime_depth=0
}

Any help will be appreciated.

justin


BillKSmith
Veteran

Jan 14, 2012, 8:00 AM

Post #2 of 7 (1172 views)
Re: [just_in] need to save the contents of the file in to a hash [In reply to] Can't Post

Use a regular expression to select the lines. Use split to separate the fields. Store the fields as a key/value pair in the hash.


Code
  

use strict;
use warnings;
use Data::Dumper qw( Dumper );
my %hash;
while (<DATA>) {
chomp;
next if ( !/(:?host_name|current_state|notifications_enabled)/ );
%hash = ( %hash, split /=/ );
}
print Dumper \%hash;
__DATA__
service {
host_name=abc.example.com
current_state=0
no_more_notifications=0
notifications_enabled=0
scheduled_downtime_depth=0
}



Note: Several unused lines removed from sample data. No efffect on code or output.
Good Luck,
Bill


FishMonger
Veteran / Moderator

Jan 14, 2012, 8:05 AM

Post #3 of 7 (1172 views)
Re: [just_in] need to save the contents of the file in to a hash [In reply to] Can't Post


Code
#!/usr/bin/perl 

use strict;
use warnings;
use Data::Dumper;

my %service;

open my $dat_fh, '<', 'status.dat' or die "failed to open 'status.dat <$!>\n";

while ( my $line = <$dat_fh> ) {
if ( $line =~ /^service {/ .. $line =~ /^}/ ) {
next if $line =~ /^(service {|})/;
chomp $line;
my ($key, $value) = split /=/, $line;
$service{$key} = $value;
}
}
close $dat_fh;

print Dumper \%service;



saurabhsharma
Novice

Jan 16, 2012, 4:00 AM

Post #4 of 7 (1068 views)
Re: [just_in] need to save the contents of the file in to a hash [In reply to] Can't Post

Hello Justin,


You do not have to loop through each and every line of your status.dat file.
Considering if the file is very large, looping through each line would make your program slow moreover file I/O always make your program slow
Instead you can use :

#!/usr/bin/perl
my @array=("host_name","current_state","notifications_enabled");
my %hash;
for $_ (@array) {
my $keyname=`grep "$_" status.dat`;
my $val=substr(substr($keyname,rindex($keyname,'=')),1);
if(($keyname ne "") && ($val ne "") {
chomp($val);
$hash{$_}=$val;
}
}

Cheers,

Saurabh Smile


FishMonger
Veteran / Moderator

Jan 16, 2012, 8:28 AM

Post #5 of 7 (1059 views)
Re: [saurabhsharma] need to save the contents of the file in to a hash [In reply to] Can't Post


Quote
You do not have to loop through each and every line of your status.dat file.

The grep command does loop over the entire file, and in this case you're doing it 4 times and each of those creates a child process. Granted that looping is implemented in C rather than Perl, but you also have the overhead of kicking off the child processes

Using substr to extract strings is usually a good approach, but I'm no so sure about using a somewhat complex statement that uses 2 calls to substr and 1 rindex. I would need to benchmark it, but I suspect that the combination of those 3 calls is slower that using split.

If there is never going to be a need to extract more than those 3 items, then I'd probably use Bill's approach. However, both his and yours becomes less desirable as you increase the number of wanted fields.


FishMonger
Veteran / Moderator

Jan 16, 2012, 8:43 AM

Post #6 of 7 (1058 views)
Re: [FishMonger] need to save the contents of the file in to a hash [In reply to] Can't Post


Code
#!/usr/bin/perl 

use strict;
use warnings;
use Benchmark qw(:all);

cmpthese(-1, {
'Fishmonger' => \&Fishmonger,
'Bill' => \&Bill,
'Saurabh' => \&Saurabh,
});


sub Fishmonger {
my %service;
open my $dat_fh, '<', 'status.dat' or die "failed to open 'status.dat <$!>\n";

while ( my $line = <$dat_fh> ) {
if ( $line =~ /^service {/ .. $line =~ /^}/ ) {
next if $line =~ /^(service {|})/;
chomp $line;
my ($key, $value) = split /=/, $line;
$service{$key} = $value;
}
}
close $dat_fh;
}

sub Bill {
my %hash;
open my $dat_fh, '<', 'status.dat' or die "failed to open 'status.dat <$!>\n";

while ( <$dat_fh> ) {
chomp;
next if ( !/(:?host_name|current_state|notifications_enabled)/ );
%hash = ( %hash, split /=/ );
}
close $dat_fh;
}

sub Saurabh {
my @array=("host_name","current_state","notifications_enabled");
my %hash;

for $_ (@array) {
my $keyname=`grep "$_" status.dat`;
my $val=substr(substr($keyname,rindex($keyname,'=')),1);
if(($keyname ne "") && ($val ne "")) {
chomp($val);
$hash{$_}=$val;
}
}
}



Code
D:\perl>benchmark.pl 
Rate Saurabh Bill Fishmonger
Saurabh 118/s -- -92% -93%
Bill 1419/s 1100% -- -13%
Fishmonger 1638/s 1286% 15% --



just_in
New User

Jan 17, 2012, 6:01 AM

Post #7 of 7 (1026 views)
Re: [just_in] need to save the contents of the file in to a hash [In reply to] Can't Post

Thanks all for the quick response. I always needs to get only these 3 values and i think Bills code is more appropriate and it works well for me.
Thanks All...

~justin

In Reply To

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives