按正则表达式组将字符串拆分为 3
Split String in 3 By REGEX Groups
我已经很多年没有使用 PERL 了,而且我有点不习惯了。
我正在根据正则表达式和搜索字符串匹配文件中的一行,当该行匹配时我会做一些 'stuff' 但我遇到困难的地方是当我尝试将该行拆分为3 个变量,其中
$one = before the match
$two = the match
$three = after the match.
下面是一些有效的代码:
(my $one = $line) =~ s/(^.+)($search)(.+$)//;
(my $two = $line) =~ s/(^.+)($search)(.+$)//;
(my $three = $line) =~ s/(^.+)($search)(.+$)//;
但是如果我能在一行中完成就更酷了。
我尝试了以下 2 个想法的多种变体
my ($one, $two, $three) = $line =~ /(^.+)($search)(.+$)/;
my ($one, $two, $three) = split(qq|/$search/|,$line);
我在谷歌上搜索过,我搜索过 PERLDOC,我在地下室翻找过,并在坚果壳中挖出了 PERL 和其他一些我多年未见的 O'REILLY。我不知道为什么我不能让它做我想做的事。
perl -v 告诉我
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
我在 Mac OS X 10.13.6
任何见解都会有所帮助和赞赏。
您实际提供了答案:
my ($one, $two, $three) = $line =~ /(^.+)($search)(.+$)/;
$ perl -M5.010 -e'
my $search = "b";
my $line = "abc\n";
my ($one, $two, $three) = $line =~ /(^.+)($search)(.+$)/;
say for $one, $two, $three;
'
a
b
c
但与您的原始代码一样,上面的代码在包含换行符的输入时可能会出现问题,它会找到最晚开始的匹配项,而不是最早开始的匹配项。以下内容更符合您的意图:
my ($one, $two, $three) = $line =~ /^(.*?)($search)(.*)/s;
最后,如果 $search
可以包含捕获,则以上两种方法都不能不进行调整。如果可能的话,您可以使用以下任一方法:
my ($one, $two, $three) = ( $line =~ /^(.*?)($search)(.*)/s )[0, 1, -1];
my ($one, $two, $three) = $line =~ /$search/ ? ($`, $&, $') : ();
如果你真的想捕获 s///
运算符的匹配组,你可以使用这样的东西:
#!/usr/bin/perl
use v5.16;
use warnings;
my $line = 'abc';
my $search = 'b';
my $new = $line =~ s/^(.+)($search)(.+)$//r;
my @match = map substr($line, $-[$_], $+[$_] - $-[$_]), 1 .. $#-;
say $new;
say "@match";
给出:
b
a b c
这并没有修改原始字符串,而且有点笨拙。
您也可以尝试使用 Perl 正则表达式的零宽度断言(不使用搜索字符串)。
你可以使用,
#!/usr/bin/perl
$string = "ABCD";
@split = $string =~ /(?=(\w{1}))/g;
print "@split\n"
这将为您提供一个包含元素 A、B、C 和 D 的数组。
我已经很多年没有使用 PERL 了,而且我有点不习惯了。
我正在根据正则表达式和搜索字符串匹配文件中的一行,当该行匹配时我会做一些 'stuff' 但我遇到困难的地方是当我尝试将该行拆分为3 个变量,其中
$one = before the match
$two = the match
$three = after the match.
下面是一些有效的代码:
(my $one = $line) =~ s/(^.+)($search)(.+$)//;
(my $two = $line) =~ s/(^.+)($search)(.+$)//;
(my $three = $line) =~ s/(^.+)($search)(.+$)//;
但是如果我能在一行中完成就更酷了。
我尝试了以下 2 个想法的多种变体
my ($one, $two, $three) = $line =~ /(^.+)($search)(.+$)/;
my ($one, $two, $three) = split(qq|/$search/|,$line);
我在谷歌上搜索过,我搜索过 PERLDOC,我在地下室翻找过,并在坚果壳中挖出了 PERL 和其他一些我多年未见的 O'REILLY。我不知道为什么我不能让它做我想做的事。
perl -v 告诉我
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level (with 2 registered patches, see perl -V for more detail)
我在 Mac OS X 10.13.6
任何见解都会有所帮助和赞赏。
您实际提供了答案:
my ($one, $two, $three) = $line =~ /(^.+)($search)(.+$)/;
$ perl -M5.010 -e'
my $search = "b";
my $line = "abc\n";
my ($one, $two, $three) = $line =~ /(^.+)($search)(.+$)/;
say for $one, $two, $three;
'
a
b
c
但与您的原始代码一样,上面的代码在包含换行符的输入时可能会出现问题,它会找到最晚开始的匹配项,而不是最早开始的匹配项。以下内容更符合您的意图:
my ($one, $two, $three) = $line =~ /^(.*?)($search)(.*)/s;
最后,如果 $search
可以包含捕获,则以上两种方法都不能不进行调整。如果可能的话,您可以使用以下任一方法:
my ($one, $two, $three) = ( $line =~ /^(.*?)($search)(.*)/s )[0, 1, -1];
my ($one, $two, $three) = $line =~ /$search/ ? ($`, $&, $') : ();
如果你真的想捕获 s///
运算符的匹配组,你可以使用这样的东西:
#!/usr/bin/perl
use v5.16;
use warnings;
my $line = 'abc';
my $search = 'b';
my $new = $line =~ s/^(.+)($search)(.+)$//r;
my @match = map substr($line, $-[$_], $+[$_] - $-[$_]), 1 .. $#-;
say $new;
say "@match";
给出:
b
a b c
这并没有修改原始字符串,而且有点笨拙。
您也可以尝试使用 Perl 正则表达式的零宽度断言(不使用搜索字符串)。 你可以使用,
#!/usr/bin/perl
$string = "ABCD";
@split = $string =~ /(?=(\w{1}))/g;
print "@split\n"
这将为您提供一个包含元素 A、B、C 和 D 的数组。