For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > April 2007 > creating hash from scalar variable









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author creating hash from scalar variable
Goksie

2007-04-29, 6:58 pm

hello,

Can someone help me correct this code.

if i print, it only print the first line.

Goksie

#!/usr/bin/perl
use strict;

my $test =
'NAS-IP-Address = 192.168.42.1
Quintum-NAS-Port = "0 0/0/c1dc2a26"
NAS-Port-Type = Async
User-Name = "192.168.42.8"
Called-Station-Id = "8600508208079"
Calling-Station-Id = ""
Acct-Status-Type = Stop
Acct-Delay-Time = 0
Acct-Input-Octets = 0
Acct-Output-Octets = 0
Acct-Session-Id = "000000C0000012F5"
Acct-Session-Time = 245
Acct-Input-Packets = 0
Acct-Output-Packets = 0
Service-Type = Login-User
Quintum-AVPair = "h323-ivr-out=ACCESSCODE:8600508208079"
Quintum-h323-conf-id = "34363262 65383833 32656366 00340000"
Quintum-AVPair = "h323-incoming-conf-id=34363262 65383833 32656366
00340000"
Quintum-h323-gw-id = "ng-la"
Quintum-h323-call-origin = "answer"
Quintum-h323-call-type = "VoIP"
Quintum-h323-setup-time = "22:58:10.220 UTC Sun Apr 22 2007"
Quintum-h323-connect-time = "22:59:09.550 UTC Sun Apr 22 2007"
Quintum-h323-disconnect-time = "22:59:09.550 UTC Sun Apr 22 2007"
Quintum-h323-remote-address = "192.168.42.8"
Quintum-h323-disconnect-cause = "1f"
Quintum-h323-voice-quality = "0"
Quintum-Trunkid-In = "192.20.42.8"
Quintum-Trunkid-Out = "10.15.115.79"
h323-incoming-conf-id = "34363262 65383833 32656366 00340000"
Client-IP-Address = 192.168.42.1
Acct-Unique-Session-Id = "87d380e1881d226c"
Timestamp = 1177282824';

my %test = my($fname, $fvalu)=split(/=/, $test);
foreach(keys %test)
{
print "$_ --- $test{$_}";
}

OUTPUT
NAS-IP-Address --- 192.168.42.1
Quintum-NAS-Port ---
Rodrick Brown

2007-04-29, 9:58 pm

On 4/29/07, Goksie <goksie@gmail.com> wrote:
> hello,
>
> Can someone help me correct this code.
>
> if i print, it only print the first line.
>
> Goksie
>
> #!/usr/bin/perl
> use strict;
>
> my $test =
> 'NAS-IP-Address = 192.168.42.1
> Quintum-NAS-Port = "0 0/0/c1dc2a26"
> NAS-Port-Type = Async
> User-Name = "192.168.42.8"
> Called-Station-Id = "8600508208079"
> Calling-Station-Id = ""
> Acct-Status-Type = Stop
> Acct-Delay-Time = 0
> Acct-Input-Octets = 0
> Acct-Output-Octets = 0
> Acct-Session-Id = "000000C0000012F5"
> Acct-Session-Time = 245
> Acct-Input-Packets = 0
> Acct-Output-Packets = 0
> Service-Type = Login-User
> Quintum-AVPair = "h323-ivr-out=ACCESSCODE:8600508208079"
> Quintum-h323-conf-id = "34363262 65383833 32656366 00340000"
> Quintum-AVPair = "h323-incoming-conf-id=34363262 65383833 32656366
> 00340000"
> Quintum-h323-gw-id = "ng-la"
> Quintum-h323-call-origin = "answer"
> Quintum-h323-call-type = "VoIP"
> Quintum-h323-setup-time = "22:58:10.220 UTC Sun Apr 22 2007"
> Quintum-h323-connect-time = "22:59:09.550 UTC Sun Apr 22 2007"
> Quintum-h323-disconnect-time = "22:59:09.550 UTC Sun Apr 22 2007"
> Quintum-h323-remote-address = "192.168.42.8"
> Quintum-h323-disconnect-cause = "1f"
> Quintum-h323-voice-quality = "0"
> Quintum-Trunkid-In = "192.20.42.8"
> Quintum-Trunkid-Out = "10.15.115.79"
> h323-incoming-conf-id = "34363262 65383833 32656366 00340000"
> Client-IP-Address = 192.168.42.1
> Acct-Unique-Session-Id = "87d380e1881d226c"
> Timestamp = 1177282824';
>
> my %test = my($fname, $fvalu)=split(/=/, $test);
> foreach(keys %test)
> {
> print "$_ --- $test{$_}";
> }
>
> OUTPUT
> NAS-IP-Address --- 192.168.42.1
> Quintum-NAS-Port ---
>
> --
> To unsubscribe, e-mail: beginners-unsubscribe@perl.org
> For additional commands, e-mail: beginners-help@perl.org
> http://learn.perl.org/
>
>
>


#!C:/Perl/bin/perl -w

use strict;
use warnings;

my $test =
'NAS-IP-Address = 192.168.42.1
Quintum-NAS-Port = "0 0/0/c1dc2a26"
NAS-Port-Type = Async
User-Name = "192.168.42.8"
Called-Station-Id = "8600508208079"
Calling-Station-Id = ""
Acct-Status-Type = Stop
Acct-Delay-Time = 0
Acct-Input-Octets = 0
Acct-Output-Octets = 0
Acct-Session-Id = "000000C0000012F5"
Acct-Session-Time = 245
Acct-Input-Packets = 0
Acct-Output-Packets = 0
Service-Type = Login-User
Quintum-AVPair = "h323-ivr-out=ACCESSCODE:8600508208079"
Quintum-h323-conf-id = "34363262 65383833 32656366 00340000"
Quintum-AVPair = "h323-incoming-conf-id=34363262 65383833 32656366
00340000"
Quintum-h323-gw-id = "ng-la"
Quintum-h323-call-origin = "answer"
Quintum-h323-call-type = "VoIP"
Quintum-h323-setup-time = "22:58:10.220 UTC Sun Apr 22 2007"
Quintum-h323-connect-time = "22:59:09.550 UTC Sun Apr 22 2007"
Quintum-h323-disconnect-time = "22:59:09.550 UTC Sun Apr 22 2007"
Quintum-h323-remote-address = "192.168.42.8"
Quintum-h323-disconnect-cause = "1f"
Quintum-h323-voice-quality = "0"
Quintum-Trunkid-In = "192.20.42.8"
Quintum-Trunkid-Out = "10.15.115.79"
h323-incoming-conf-id = "34363262 65383833 32656366 00340000"
Client-IP-Address = 192.168.42.1
Acct-Unique-Session-Id = "87d380e1881d226c"
Timestamp = 1177282824';

use Data::Dumper;
my %h;
map { $h{$_->[0]}=$_->[1] } map { [ split/=/,$_ ] } split/\n/,$test;
print Dumper(\%h);

--
Rodrick R. Brown
http://www.rodrickbrown.com
Rob Dixon

2007-04-29, 9:58 pm

Rodrick Brown wrote:
>
> use Data::Dumper;
> my %h;
> map { $h{$_->[0]}=$_->[1] } map { [ split/=/,$_ ] } split/\n/,$test;
> print Dumper(\%h);


Or, more intelligibly,

my %h;

foreach (split /\n/, $test) {
my ($key, $val) = split /=/;
$h{$key} = $val;
}

Rob
Matthew J. Avitable

2007-04-29, 9:58 pm

Given the original string ...
> my $test =
> 'NAS-IP-Address = 192.168.42.1
> .......
> Acct-Unique-Session-Id = "87d380e1881d226c"
> Timestamp = 1177282824';
>


You could also invoke perl 5.8's ability to treat an in-memory string as
a file:

## get a filehandle on $test
open(my $fh, '<', \$test) or die "Unable to open scalar ref for reading:
$!";

while (my $line = <$fh> ) {

## split on '=' with a max of two resulting fields, clear spaces
adjacent to '='.
## clear newlines as well.
chomp ( my ($k, $v) = split(/\s*=\s*/, $line, 2) );

## clear out the quotes in the value
$v =~ s/"//og;

## do something with your key and value:
print "Key is $k, Value is: $v\n";

}

close $fh;


Reading a file line by line is a fairly recognizable pattern to perl
programmers of all levels, so it may assist future maintainers.

Hope this helps!

-m
Randal L. Schwartz

2007-04-30, 6:58 pm

>>>>> ""Matthew" == "Matthew J Avitable" <mja@richweb.com> writes:

"Matthew> You could also invoke perl 5.8's ability to treat an in-memory string as a
"Matthew> file:

You can, but that's rapidly sliding into "obfuscation" territory. You already
have the data... why shove it out as a filehandle and back in line by line,
when all you need to do is split the data up by lines?

string-as-filehandle is mostly to work around legacy systems that want a
filehandle but you actually want the data in memory. Don't invent *new*
interfaces that *require* their use. Ugh.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Rob Dixon

2007-04-30, 6:58 pm

Matthew J. Avitable wrote:
>
> Given the original string ...
>
> You could also invoke perl 5.8's ability to treat an in-memory string as
> a file:
>
> ## get a filehandle on $test
> open(my $fh, '<', \$test) or die "Unable to open scalar ref for reading: $!";
>
> while (my $line = <$fh> ) {


Hmm. I don't feel this is an improvement over just

foreach (split /\n/, $line) {
:
}

or even

while ($test =~ /(.*\n?)/g) {
my $line = $1;
:
}

to avoid duplicating the whole string at once.

> ## split on '=' with a max of two resulting fields, clear spaces adjacent to '='.
> ## clear newlines as well.
> chomp ( my ($k, $v) = split(/\s*=\s*/, $line, 2) );


Why chomp here? You're chomping $k, which /can't/ end in a record, as well as $v.
Just

chomp $line;
my ($k, $v) = split /\s*=\s*/, $line, 2;

is more appropriate.

>
> ## clear out the quotes in the value
> $v =~ s/"//og;


Why use the /o modifier when there are no variables being interpolated into
the regex?

Even better (in terms of speed) would be

$v =~ tr/"//d;

although I admit I tend to use s/// exclusively myself.

Also why remove the quotes when the OP didn't say he wanted to, and may actually
need them?

> ## do something with your key and value:
> print "Key is $k, Value is: $v\n";
>
> }
>
> close $fh;
>
>
> Reading a file line by line is a fairly recognizable pattern to perl
> programmers of all levels, so it may assist future maintainers.


....unless it stops working, when opening a string on a filehandle is a
fairly /unrecognisable/ pattern, and the maintainer may be stumped!

Cheers,

Rob
Goksie

2007-04-30, 6:58 pm

Rob Dixon wrote:
> Matthew J. Avitable wrote:
>
> Hmm. I don't feel this is an improvement over just
>
> foreach (split /\n/, $line) {
> :
> }
>
> or even
>
> while ($test =~ /(.*\n?)/g) {
> my $line = $1;
> :
> }
>
> to avoid duplicating the whole string at once.
>
>
> Why chomp here? You're chomping $k, which /can't/ end in a record, as
> well as $v.
> Just
>
> chomp $line;
> my ($k, $v) = split /\s*=\s*/, $line, 2;
>
> is more appropriate.
>
>
> Why use the /o modifier when there are no variables being interpolated
> into
> the regex?
>
> Even better (in terms of speed) would be
>
> $v =~ tr/"//d;
>
> although I admit I tend to use s/// exclusively myself.
>
> Also why remove the quotes when the OP didn't say he wanted to, and
> may actually
> need them?
>
>
> ...unless it stops working, when opening a string on a filehandle is a
> fairly /unrecognisable/ pattern, and the maintainer may be stumped!
>
> Cheers,
>
> Rob
>

i have tried all,

and I still stand by my confidence that perl community is still the most
vibrant of all.

Thank you all,

Goksie
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com