尝试使用Text :: CSV_XS来解析一些日志。但是,以下代码不符合我的预期 - 根据分隔符" "
将行拆分为多个部分。
有趣的是,如果我删除字符串$a
中的双引号,那么它将进行拆分。
不知道这是一个错误还是我遗漏了什么。谢谢!
use Text::CSV_XS;
$a = 'id=firewall time="2010-05-09 16:07:21 UTC"';
$userDefinedSeparator = Text::CSV_XS->new({sep_char => " "});
print "$userDefinedSeparator\n";
$userDefinedSeparator->parse($a);
my $e;
foreach $e ($userDefinedSeparator->fields) {
print $e, "\n";
}
修改
在上面的代码段中,我将=
(在time
之后)更改为空格,然后才能正常工作。开始想知道这是不是一个bug呢?
$a = 'id=firewall time "2010-05-09 16:07:21 UTC"';
答案 0 :(得分:3)
如果您实际上没有尝试解析csv数据,可以使用Text::ParseWords
来获取时间字段,这是Perl 5中的核心模块。使用此模块的好处是它可以很好地处理报价
use strict;
use warnings;
use Data::Dumper;
use Text::ParseWords;
my $str = 'id=firewall time="2010-05-09 16:07:21 UTC"';
my @fields = quotewords(' ', 0, $str);
print Dumper \@fields;
my %hash = map split(/=/, $_, 2), @fields;
print Dumper \%hash;
<强>输出:强>
$VAR1 = [
'id=firewall',
'time=2010-05-09 16:07:21 UTC'
];
$VAR1 = {
'time' => '2010-05-09 16:07:21 UTC',
'id' => 'firewall'
};
我还介绍了如何通过将数据添加到哈希来使数据更易于访问。请注意,哈希不能包含重复的键,因此您需要为每个新的time
键添加新的哈希值。
答案 1 :(得分:2)
您将引号字符和转义字符集都保留为双引号"
,然后将它们嵌入要分割的字段中,从而混淆了模块。
同时禁用quote_char
和escape_char
use strict;
use warnings;
use Text::CSV_XS;
my $string = 'id=firewall time="2010-05-09 16:07:21 UTC"';
my $space_sep = Text::CSV_XS->new({
sep_char => ' ',
quote_char => undef,
escape_char => undef,
});
$space_sep->parse($string);
for my $field ($space_sep->fields) {
print "$field\n";
}
<强>输出强>
id=firewall
time="2010-05-09
16:07:21
UTC"
但是 note 你已经完成了与print "$_\n" for split ' ', $string
完全相同的事情,这是首选,因为它更有效,更简洁。
此外,您必须始终 use strict
和use warnings
;并且从不使用$a
或$b
作为变量名,因为它们被sort
使用,因为它们毫无意义且不具备描述性。
<强>更新强>
正如@ThisSuitIsBlackNot
指出的那样,你的意图可能不是分裂空格而是提取一系列key=value
对。如果是这样,那么此方法将值直接放入哈希值。
use strict;
use warnings;
my $string = 'id=firewall time="2010-05-09 16:07:21 UTC"';
my %data = $string =~ / ([^=\s]+) \s* = \s* ( "[^"]*" | [^"\s]+ ) /xg;
use Data::Dump;
dd \%data;
<强>输出强>
{ id => "firewall", time => "\"2010-05-09 16:07:21 UTC\"" }
<强>更新强>
此程序将提取两个name=value
字符串并在不同的行上打印。
use strict;
use warnings;
my $string = 'id=firewall time="2010-05-09 16:07:21 UTC"';
my @fields = $string =~ / (?: "[^"]*" | \S )+ /xg;
print "$_\n" for @fields;
<强>输出强>
id=firewall
time="2010-05-09 16:07:21 UTC"