拥有类似HTML属性的字符串
key1="value1 value2" key2="va3" key4
需要解析这样的字符串来获得HoA:
$parsed = {
key1' => [
'value1',
'value2'
],
key2 => [ 'val3' ], #or key2 => 'val3' doesn't matter..
key4 => undef,
};
自己创建函数,例如:
#!/usr/bin/env perl
use 5.014;
use strict;
use warnings;
use Data::Dumper;
while(<DATA>) {
my $parsed;
chomp;
next if m/\A\s*#/;
while( m/(\w+)(\s*=\s*(["'])(.*?)(\3))?/g ) {
my $k = $1;
if( $4 ) {
my @v = split(/\s+/, $4);
$parsed->{$k} = \@v;
}
else {
$parsed->{$k} = undef;
}
}
say Dumper $parsed;
}
__DATA__
key1="value1 value2" key2 key3="val3"
key1='value1 "value2"' key8 key3='val3'
key1='value1 i\'m' key2 key3="val3"
key1='value1 value2' key8 key3=val3
工作并打印前两行的正确结果。
$VAR1 = {
'key1' => [
'value1',
'value2'
],
'key3' => [
'val3'
],
'key2' => undef
};
$VAR1 = {
'key1' => [
'value1',
'"value2"'
],
'key3' => [
'val3'
],
'key8' => undef
};
不幸的是,它在第3行失败 - 不知道如何处理转义的引号。 (而且只是想出key=val
(没有引号)也是有效的))
@mpapec提出了一个模块,这对解析“assignement”的RHS部分有很大帮助。我的问题是字符串包含多个空格分隔LHS=RHS
,其中RHS可以引用(单引号和双引号)或不引用(在一个值的情况下)和RHS值(在引号中)是空格也划定了..
key1="value1 value2" key2="va3" key4 key5=val5 key6='val6' key7='val x\'y zzz'
所以我不知道如何将字符串分成多个LHS=RHS
部分,因为无法在空间拆分而无法使用我的正则表达式,因为它在转义失败引号。 (也许一些更复杂的正则表达式处理转义可以工作)。
有什么建议吗?
答案 0 :(得分:2)
您可以使用Text::ParseWords
作为mpapec建议:
use strict;
use warnings;
use 5.010;
use Data::Dumper;
use Text::ParseWords;
$Data::Dumper::Sortkeys = 1;
my $string = q{key1="value1 value2" key2="va3" key4 key5=val5 key6='val6' key7='val x\'y zzz'};
my @words = shellwords $string;
my %parsed;
foreach my $word (@words) {
my ($key, $values) = split /=/, $word, 2;
$parsed{$key} //= [];
push @{ $parsed{$key} }, $_ for shellwords $values;
}
print Dumper \%parsed;
$VAR1 = {
'key1' => [
'value1',
'value2'
],
'key2' => [
'va3'
],
'key4' => [],
'key5' => [
'val5'
],
'key6' => [
'val6'
],
'key7' => [
'val',
'x\'y',
'zzz'
]
};
请注意,为了保持一致性,我将没有值的键分配为空数组而不是undef
。我认为这将使数据结构更易于使用。
另请注意,我两次致电shellwords
。我这样做是为了从转义引号中删除反斜杠,所以
key7='val x\'y zzz'
分为
val x'y zzz
而不是
val x\'y zzz
(上面输出中x\'y
中的反斜杠由Data::Dumper
添加;变量本身没有反斜杠。)
答案 1 :(得分:1)
要解决当前问题,您可以设置更改以特殊方式处理反斜杠。
#!/usr/bin/env perl
use 5.014;
use strict;
use warnings;
use Data::Dump;
my $parsed;
while (<DATA>) {
chomp;
next if m/\A\s*#/;
while (
m{
(\w+)
(?:
\s* = \s*
(["'])
( (?: (?!\2)[^\\] | \\. )* )
\2
)?
}gx
)
{
my $k = $1;
if ($2) {
( my $val = $3 ) =~ s/\\(.)/$1/g; # Unescape backslashes
$parsed->{$k} = [ split /\s+/, $val ]; # Split words
} else {
$parsed->{$k} = undef;
}
}
dd $parsed;
print "\n";
}
__DATA__
key1="value1 value2" key2 key3="val3"
key1='value1 "value2"' key2 key3='val3'
key1='value1 i\'m' key2 key3="val3"
输出:
{ key1 => ["value1", "value2"], key2 => undef, key3 => ["val3"] }
{ key1 => ["value1", "\"value2\""], key2 => undef, key3 => ["val3"] }
{ key1 => ["value1", "i'm"], key2 => undef, key3 => ["val3"] }
还有其他问题需要考虑,但这可能有助于您进一步发展。
答案 2 :(得分:0)
你可能会考虑基于Parser :: MGC的东西。
上的示例看起来就像一个很好的简单循环my $key = $self->token_ident;
$self->expect( '=' );
my $value = $self->token_string;