说我有一个字符串:
my $string = "foo{a},bar{b}, baz{c,d,e}";
使用一组分组字符来区分两个级别:
$grouping_characters = "{}"
我想将此字符串拆分为“外部”逗号(,
),尊重$grouping_characters
内的所有内容。
对于上面的示例,输出应为:
my @result = ("foo{a}", "bar{b}", "baz{c,d,e}")
我如何在Perl中执行此操作?
答案 0 :(得分:3)
首先:如果要正确解析某些编程语言或配置格式,可能需要使用actual parser。
但是,您的任务可以通过正则表达式完成。但是我们不会写一个正则表达式来匹配我们想要拆分的逗号。相反,我们编写了一个与列表部分匹配的正则表达式:
my $regex = qr/
\w+ # item can begin with some identifier
\{ [^\}]* \} # followed by some stuff in braces
[,;] # must end with comma or semicolon
/x;
然后我们可以提取像
这样的匹配项my $string = "foo{a},bar{b}, baz{c,d,e};";
my @result = $string =~ /$regex/g;
dd @result; # using dd from Data::Dump
输出:
("foo{a},", "bar{b},", "baz{c,d,e};")
非常好。现在,我们以两种方式改进我们的正则表达式:
合:
my $delims = quotemeta "{}";
my $regex = qr/
\w+
[$delims] [^$delims]* [$delims]
/x;
my $string = "foo{a},bar{b}, baz{c,d,e};";
my @result = $string =~ /\G ($regex) [,;] \s*/xg;
dd @result;
\G
断言锚定上一场比赛停止的位置。
输出:
("foo{a}", "bar{b}", "baz{c,d,e}")
奇妙。这可以通过两种方式进一步完善:
foo}a{
将是一个有效的项目...... 如果不需要所有这些,那么当前的正则表达式应该可以。
答案 1 :(得分:1)
尝试使用此正则表达式:
(.*[}]),\s*(.*[}]),\s*(.*[{].*[}])
像这样:
my $string = "foo{a},bar{b}, baz{c,d,e}";
print grep(/(.*[}]),\s*(.*[}]),\s*(.*[{].*[}])/, $string);
答案 2 :(得分:1)
你可以尝试:
my $string = "foo{a},bar{b}, baz{c,d,e}";
print join(",",split(/,\s*(?=\w+{[a-z,]+})/g,$string));
答案 3 :(得分:1)
简单解析器:
#!/usr/bin/perl
use warnings;
use strict;
my $string = 'foo{a},bar{b}, baz{c,d,e}';
my @parts;
my $inside;
my $from = 0;
for my $i (0 .. length $string) {
my $char = substr $string, $i, 1;
if ('{' eq $char) {
$inside++;
} elsif ('}' eq $char) {
$inside--
} elsif (',' eq $char and not $inside) {
push @parts, substr $string, $from, $i - $from;
$from = $i + 1;
}
}
push @parts, substr $string, $from;
print "$_\n" for @parts;
删除空格留给读者练习。
答案 4 :(得分:0)
> echo "foo{a},bar{b}, baz{c,d,e}" | perl -lne 'push @a,/.*?{.*?},?/g;for(@a){print}'
foo{a},
bar{b},
baz{c,d,e}
>