我正在尝试匹配配置文件中的所有出现并将其存储在散列变量中的perl中。这是我要解析的配置文件:
# commented area
# still commenting
Key1: Value1
Key2: 2013/03/04 15:41:30
Key3: Value with spaces whatever you pass here fits
Key4:
value5
value6
value7
Key5:
some other multiline value
for testing purpose
我已经创建了这个正则表达式,遗憾的是它没有完全正常运行。 Key4
仅包含value5
,而Key5
完全缺失。
正则表达式:
/^(\w+)\:\s*(.+?)(?=^[^\:]+\:)/smg
知道如何改进吗?
答案 0 :(得分:1)
您可以尝试这样的事情:
^(\w+):\s*(.+?)(?=^[^\n\r:]+:|\z)
我删除了冒号(:
)上的转义符,并在否定的类中插入了\n\r
。在(?=^[^\:]+\:)
结束时value5
被(.+?)
标记为\r\n
,因此(.+?)
不愿意继续匹配。
使用内部的^[^:]+:
会强制|\z
匹配,直到下一行包含^(\w+):\s*((?:(?!^[^\r\n:]+:|^#).)+)
。
然后我添加了.+?
以使正则表达式匹配直到结束。然而问题是它可能还会捕获评论,如果上述内容不合适,可能就是这样吗?
.+
这一次,我将key
变成了贪婪的^[^\r\n:]+:
并添加了对每个字符匹配的检查:下一行的格式不是^#
(即匹配{{1}}和换行符再次出现与前面提到的相同的原因)或注释行({{1}})。可能的问题是值之间的注释或不在行开头的注释将进入值。
实际上应该有配置文件解析器,我认为这对于这类任务会更好。
答案 1 :(得分:0)
此看起来像libyaml
C库)来解析文件并将其存储在标量中:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use YAML::XS;
my $yaml = YAML::XS::LoadFile('config.yaml');
print Dumper $yaml;
$VAR1 = {
'Key5' => 'some other multiline value for testing purpose',
'Key2' => '2013/03/04 15:41:30',
'Key1' => 'Value1',
'Key4' => 'value5 value6 value7',
'Key3' => 'Value with spaces whatever you pass here fits'
};
请注意$yaml
是哈希引用。
*假设value5
,value6
和value7
组成单个标量而不是序列中的多个元素。同时假设您的多行值不包含任何标签:
或#
。这肯定是假设很多,但可能适用于你的情况。
答案 2 :(得分:0)
这有点晚了。
我认为正则表达式应该是一个简单的,面向行的
真正的逻辑是在匹配的体内。
这就像我会这样做(有很多方法,这是基本的)。
( ^ [^#:\n]+ ) # (1), Key
: # :
| # or,
(?: ^ [^\S\n]* \# .* \n? ) # BOL comments
| # or,
\# .* # EOL comments
| # or,
( [^#\n]* \n? ) # (2), Line value
Perl测试用例
$/ = undef;
$str = <DATA>;
$key = undef;
$keyval = "";
%keyhash = ();
@order = ();
while ($str =~ /(^[^#:\n]+):|(?:^[^\S\n]*\#.*\n?)|\#.*|([^#\n]*\n?)/mg)
{
if ( defined $1 ) {
if (defined $key) {
$keyval =~ s/\s+$//;
$keyhash{ $key } = $keyval;
}
($key, $keyval) = ($1,"");
$keyhash{ $key } = "";
push @order, $key;
next;
}
if ( defined $2 && defined $key ) {
$keyval .= $2;
}
}
if ( defined $key ) {
$keyval =~ s/\s+$//;
$keyhash{ $key } = $keyval;
}
foreach $key ( @order ) {
print "'$key' = '$keyhash{$key}'\n";
}
__DATA__
# commented area
Key0:
# still commenting
Key1: Value1
Key2: 2013/03/04 15:41:30 # line end comment
#asfgasfg
stuff
#asfgasfg
here
Key3: Value with spaces whatever you pass here fits
Key4:
value5
value6
value7
Key5:
some other multiline value
for testing purpose
输出&gt;&gt;
'Key0' = ''
'Key1' = ' Value1'
'Key2' = ' 2013/03/04 15:41:30
stuff
here'
'Key3' = ' Value with spaces whatever you pass here fits'
'Key4' = '
value5
value6
value7'
'Key5' = '
some other multiline value
for testing purpose'