按正则表达式组将字符串拆分为 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 的数组。