我正在尝试解析一系列元素。符合以下模式的人:
Jim("jjanson", Customer.SALES);
我想创建一个像Jim => "jjanson"
一样的哈希表
我怎样才能做到这一点?
我无法匹配使用的线:
if($line =~ /\s*[A-Za-z]*"(.*),Customer.*\s*/)
答案 0 :(得分:2)
在“客户”之前,您没有匹配名称后面的'('
和逗号后面的' '
。
我可以使用以下表达式获取'jjanson"'
:
/\s*[A-Za-z]\(*"(.*), Customer.*\s*/
但我认为你不想要jjanson
"
,所以我们需要像这样修改它。 (当我在寻找简单划分的东西时,我倾向于包含负面字符类。所以,在这种情况下,我将表达"[^"]*"
/\s*[A-Za-z]\(*"([^"]+)", Customer.*\s*/
另外,我尽量不依赖于空格,存在或数字,我将用\s*
替换空格。你没有注意到你跳过了空白,这很好地说明了需要说“忽略一堆空白”。
/\s*[A-Za-z]\(*"([^"]+)",\s*Customer.*\s*/
现在它只在重要字符中查找序列','
+ 'Customer'
。在功能上,相同,如果更灵活。
但是因为你只做了一次捕获,所以我看不出你要映射到什么。所以我会做自己的映射:
my %records;
while ( my $line = $source->()) { # simply feed for a source of lines.
my ( $first, $user, $tag )
= $line = m/\s*(\p{Alpha}+)\s*\(\s*"([^"]+)",\s*Customer\.(\S+?)\)\/
;
$records{ $user }
= { first => $first
, username => $user
, tag => $tag
};
}
这比一次性快速解决方案所需要的要多得多。但我喜欢尽可能多地存储我的输入。
答案 1 :(得分:0)
请注意Jim("jjanson", Customer.SALES);
匹配具有两个参数的函数调用的语法。因此,您可以滥用string eval
:
#!/usr/bin/env perl
use strict;
use warnings;
use YAML::XS;
my $info = extract_first_arg(q{ Jim("jjanson", Customer.SALES);} );
print Dump $info;
sub extract_first_arg {
my $call = shift;
my ($name) = ($call =~ m{ \A \s* (\w+) }x);
unless ($name) {
warn "Failed to find function name in '$call'";
return;
}
my $username = eval sprintf(q{
package My::DangerZone;
no strict;
local *{ %s } = sub { $_[0] };
%s
}, $name, $call);
return { $name => $username };
}
输出:
--- Jim: jjanson
或者,您可以滥用autoloading:
our $AUTOLOAD;
print Dump eval 'no strict;' . q{ Jim("jjanson", Customer.SALES); };
sub AUTOLOAD {
my ($fn) = ($AUTOLOAD =~ /::(\w+)\z/);
return { $fn => $_[0] };
}
我不一定建议使用这些方法,特别是对于不在您控制范围内的输入,以及此脚本可以访问敏感设施的情况。
另一方面,在适当的情况下,我利用这种方式将一组给定的信息转换成可以在其他地方使用的东西。
答案 2 :(得分:0)
试试这个:
$line = 'Jim("jjanson", Customer.SALES)';
my %hashStore = (); #Jim("jjanson"
if($line=~m/^\s*([^\(\)]*)\(\"([^\"]*)\"/g) { $hashStore{$1} = $2; }
use Data::Dumper;
print Dumper \%hashStore;
输出:
$VAR1 = {
'Jim' => 'jjanson'
};