Reputation: 249
Basically I'm trying to take certain keywords in a string along with the accompanying text to be put in a hash.
A sample string:
!add-action-item :date 03/29/2012 :task Go to the bathroom :prio 1
Code snip:
when(/^!add-action-item/) {
my ($date, $prio, $task) = $what =~ /:date\s(\d{2}\/\d{2}\/\d{4})\s|:prio\s(\d+)\s|:task\s(.*)/;
print Dumper($date, $prio, $task);
}
So basically I'd like to have predefined attributes like :date, :prio, :task and convert those into
%ash = ( date => $date,
prio => $prio,
task => $task
)
Eventually I'd like to just accept any attribute and place into a key value pair and just act on the ones I care about. Im pretty noobish when it comes to perl so I apologize if this is something builtin I missed in the documentation.
Thanks
Upvotes: 1
Views: 247
Reputation: 4429
You can not capture all three groups using |
.
Fix your regex and then build your data structure from the capturing groups.
use strict;
use warnings;
use Data::Dumper;
my $string = '!add-action-item :date 03/29/2012 :task Go to the bathroom :prio 1';
if ( $string =~ /^!add-action-item/ ) {
$string =~ m[
\s+:date\s(\d{2}/\d{2}/\d{4})
\s+:task\s(.*)
\s+:prio\s(\d+)
]x;
my $data = {
date => $1,
task => $2,
prio => $3,
};
print Dumper $data;
}
__END__
$VAR1 = {
'date' => '03/29/2012',
'prio' => '1',
'task' => 'Go to the bathroom'
};
Upvotes: 3
Reputation: 385917
I don't like the idea of looking for specific fields in a specific order. mugen kenichi's solution will fail if a 4th field is added, for example.
Here's a more robust solution by virtue of being more generic:
my $cmd = '!add-action-item :date 03/29/2012 :task Go to the bathroom :prio 1';
for ($cmd) {
/\G ! (\S+) /xgc or die;
my $action = $1;
my %args;
for (;;) {
last if /\G \s* \z /xgc;
/\G \s+ :(\S+) /xgc or die;
my $name = $1;
/\G \s+ ([^\s:]\S*(?:\s+[^\s:]\S*)*) /xgc or die;
my $val = $1;
$args{$name} = $val;
}
# Do something with $action and %args here.
}
Alternative implementation:
my $cmd = '!add-action-item :date 03/29/2012 :task Go to the bathroom :prio 1';
{
my ($action, @args) = split /\s+:/, $cmd;
$action =~ s/^!//;
$action =~ s/\s+\z//;
my %args;
for my $arg (@args) {
my ($name, $val) = split(' ', $arg, 2);
$args{$name} = $val;
}
# Do something with $action and %args here.
}
For example, if you use
use Data::Dumper qw( Dumper );
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Terse = 1;
printf("action: %s\n", $action);
printf("args: %s\n", Dumper(\%args));
You get:
action: add-action-item
args: {'date' => '03/29/2012','prio' => '1','task' => 'Go to the bathroom'}
Parse::RecDescent grammar (untested):
parse : command /\Z/ { $item[1] }
command : action arg(s) { [ $item[1], { map @$_, @{$item[2]} } ] }
action : /!\S+/ { substr($item[1], 1) }
arg_name : /:\S+/ { substr($item[1], 1) }
arg_val : /[^\s:]\S*(?:\s+[^\s:]\S*)*/
Upvotes: 2
Reputation: 7516
use Data::Dumper;
my @array = qw(Today stat bigone);
my %hash;
@hash{qw( date prio task )} = @array;
print Dumper \%hash;
$VAR1 = {
'date' => 'Today',
'prio' => 'stat',
'task' => 'bigone'
};
Upvotes: 2