我的输入文件如下:
HEADER
{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}
{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}
{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}
{ABC|*|XYZ:ghi:jkl {JKL 0 372 0} {{Points {}}}}
{ABC|*|XYZ:mno:pqr {GHI 0 34 0} {{Points {}}}}
{
ABC|*|XYZ:abc:pqr {GHI 0 68 0}
{{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
}
TRAILER
我想将文件解压缩到如下数组:
$array[0] = "{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}"
$array[1] = "{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}"
$array[2] = "{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}"
..
..
$array[5] = "{
ABC|*|XYZ:abc:pqr {GHI 0 68 0}
{{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
}"
这意味着,我需要将第一个开口大括号与其右大括号相匹配,并在中间提取字符串。
我已查看以下链接,但这不适用于我的问题。 Regex to get string between curly braces "{I want what's between the curly braces}"
我正在尝试,但如果有人可以帮助我提供他们的专业知识,那将会非常有帮助......
由于 斯里兰卡......
答案 0 :(得分:15)
答案 1 :(得分:13)
至少在现代版本的Perl中,当然可以使用正则表达式来完成:
my @array = $str =~ /( \{ (?: [^{}]* | (?0) )* \} )/xg;
print join "\n" => @array;
正则表达式匹配一个大括号块,它包含非大括号字符或递归到自身(匹配嵌套大括号)
编辑:上面的代码在Perl 5.10+中工作,对于早期版本,递归有点冗长:
my $re; $re = qr/ \{ (?: [^{}]* | (??{$re}) )* \} /x;
my @array = $str =~ /$re/xg;
答案 2 :(得分:4)
我第二次建议使用Text::Balanced
模块。几行就能让你上路。
use strict;
use warnings;
use Text::Balanced qw/extract_multiple extract_bracketed/;
my $file;
open my $fileHandle, '<', 'file.txt';
{
local $/ = undef; # or use File::Slurp
$file = <$fileHandle>;
}
close $fileHandle;
my @array = extract_multiple(
$file,
[ sub{extract_bracketed($_[0], '{}')},],
undef,
1
);
print $_,"\n" foreach @array;
{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}
{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}
{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}
{ABC|*|XYZ:ghi:jkl {JKL 0 372 0} {{Points {}}}}
{ABC|*|XYZ:mno:pqr {GHI 0 34 0} {{Points {}}}}
{
ABC|*|XYZ:abc:pqr {GHI 0 68 0}
{{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
}
答案 3 :(得分:2)
我不认为纯正则表达式是你想要在这里使用的(恕我直言,这可能甚至不能使用正则表达式进行解析)。
相反,构建一个小解析器,类似于此处显示的:http://www.perlmonks.org/?node_id=308039 (参见dbgunefx(Parson)于2003年11月18日18:29 UTC的答案)
更新似乎可以使用正则表达式 - 我在Mastering Regular Expressions中看到了对匹配嵌套括号的引用(可以在Google Books上找到,因此如果你不喜欢,可以使用google搜索没有这本书 - 见第5章“匹配平衡的括号集”一节
答案 4 :(得分:2)
您可以随时计算大括号:
my $depth = 0;
my $out = "";
my @list=();
foreach my $fr (split(/([{}])/,$data)) {
$out .= $fr;
if($fr eq '{') {
$depth ++;
}
elsif($fr eq '}') {
$depth --;
if($depth ==0) {
$out =~ s/^.*?({.*}).*$/$1/s; # trim
push @list, $out;
$out = "";
}
}
}
print join("\n==================\n",@list);
这是旧的,简单的Perl风格(可能很丑陋)。
答案 5 :(得分:0)
对于这种类型的解析,使用状态机比使用正则表达式要好得多。
答案 6 :(得分:0)
正则表达式对于匹配大括号实际上非常糟糕。根据你想要的深度,你可以为Parse::RecDescent写一个完整的语法(这比听起来容易得多!)。或者,如果您只想获得块,请搜索打开“{”标记并关闭“}”,并且只计算在任何给定时间打开的数量。