Loading a hash from a string containing newlines

S

Scott Bass

Hi,

my $var = "TESTID: A\nB\nOBJECTIVE: C\nD\nPROCEDURE: E\nF\nRESULTS: G\nH\n";
my %hash = $var =~ /(TESTID|OBJECTIVE|PROCEDURE|RESULTS):(.+)/mg;
print $hash{"TESTID"};
print $hash{"OBJECTIVE"};
print $hash{"PROCEDURE"};
print $hash{"RESULTS"};

1. How can I get $hash{"TESTID"} = "A\nB", etc.?

2. (Minor) How can I make the hash keys lowercase? The search needs to be
case-sensitive, and the text must be in upper case?

Sorry if this is in the docs (just point me to it). I searched the doc,
Googled, and skimmed a couple O'Reilly books before posting.

Thanks,
Scott
 
D

Dave Weaver

my $var = "TESTID: A\nB\nOBJECTIVE: C\nD\nPROCEDURE: E\nF\nRESULTS: G\nH\n";
my %hash = $var =~ /(TESTID|OBJECTIVE|PROCEDURE|RESULTS):(.+)/mg;
1. How can I get $hash{"TESTID"} = "A\nB", etc.?

In order for '.' to match a newline, you'll need the /s modifier, not
/m. However, this then causes .+ to be too greedy, so further checks
are required:

my %hash = $var =~ /(TESTID|OBJECTIVE|PROCEDURE|RESULTS): (.+?)(?=\n\w+:|$)/sg;

2. (Minor) How can I make the hash keys lowercase?

while ( $var =~ /(TESTID|OBJECTIVE|PROCEDURE|RESULTS): (.+?)(?=\n\w+:|$)/sg ) {
$hash{ lc $1 } = $2;
}
 
S

Steven Kuo

Hi,

my $var = "TESTID: A\nB\nOBJECTIVE: C\nD\nPROCEDURE: E\nF\nRESULTS: G\nH\n";
my %hash = $var =~ /(TESTID|OBJECTIVE|PROCEDURE|RESULTS):(.+)/mg;
print $hash{"TESTID"};
print $hash{"OBJECTIVE"};
print $hash{"PROCEDURE"};
print $hash{"RESULTS"};

1. How can I get $hash{"TESTID"} = "A\nB", etc.?

2. (Minor) How can I make the hash keys lowercase? The search needs to be
case-sensitive, and the text must be in upper case?

Sorry if this is in the docs (just point me to it). I searched the doc,
Googled, and skimmed a couple O'Reilly books before posting.

Thanks,
Scott



Among the many ways to do this:

package LCKeys;
require Tie::Hash;
@ISA = ('Tie::StdHash');

sub STORE
{
$_[0]{ lc($_[1]) } = $_[2];
}
1;

package main;
use Data::Dumper;

my %h1;
tie %h1, 'LCKeys';

my $var = "TESTID: A\nB\nOBJECTIVE: C\nD\nPROCEDURE: E\nF\nRESULTS: G\nH\n";
%h1 = grep $_, split(/(TESTID|OBJECTIVE|PROCEDURE|RESULTS):/, $var);

print Dumper \%h1;

my %h2;
my $key;

require 5.8.0;
open (my $fh, '<', \$var)
or die $!;

while (<$fh>)
{
if (/(TESTID|OBJECTIVE|PROCEDURE|RESULTS):(.+)/s)
{
$key = lc($1);
$h2{$key} = $2;
}
else
{
$h2{$key} .= $_;
}
}

print Dumper \%h2;


For details, see:

perldoc -f open
perldoc -f split
perldoc Tie::Hash
 
J

John W. Krahn

Scott said:
my $var = "TESTID: A\nB\nOBJECTIVE: C\nD\nPROCEDURE: E\nF\nRESULTS: G\nH\n";
my %hash = $var =~ /(TESTID|OBJECTIVE|PROCEDURE|RESULTS):(.+)/mg;
print $hash{"TESTID"};
print $hash{"OBJECTIVE"};
print $hash{"PROCEDURE"};
print $hash{"RESULTS"};

1. How can I get $hash{"TESTID"} = "A\nB", etc.?

2. (Minor) How can I make the hash keys lowercase? The search needs to be
case-sensitive, and the text must be in upper case?

Sorry if this is in the docs (just point me to it). I searched the doc,
Googled, and skimmed a couple O'Reilly books before posting.

john@perl Combs $ perl -MData::Dumper -e'
my $var = "TESTID: A\nB\nOBJECTIVE: C\nD\nPROCEDURE: E\nF\nRESULTS: G\nH\n";
my %hash = map { ($a,$b) = split /:/; lc $a, $b }
$var =~ /((?:TESTID|OBJECTIVE|PROCEDURE|RESULTS):.+?)(?=\n\w+:|$)/sg;
print Dumper \%hash;
'
$VAR1 = {
'testid' => ' A
B',
'procedure' => ' E
F',
'objective' => ' C
D',
'results' => ' G
H'
};



John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top