我尝试了几种方法来解决上次出现的问题,但都不起作用。以下是我的案例,
abc def = ghi
abc def ghi = jkl
abc def ghi=jkl mno
对于第一行,我的捕获目标是"def"。第二行,我的捕获目标是"ghi",第三行,我捕获的目标是"ghi"。目标可以口头表达为"等号前单词的最后一次出现"。
Perl的正则表达式应该是什么样子?
您可以使用此模式
(w+)(?=s*=)
演示
( # Capturing Group (1)
w # <ASCII letter, digit or underscore>
+ # (one or more)(greedy)
) # End of Capturing Group (1)
(?= # Look-Ahead
s # <whitespace character>
* # (zero or more)(greedy)
= # "="
) # End of Look-Ahead
b(w+)s*=
对于您的示例就足够了。它匹配一个单词,可选地紧跟空白,紧跟=
。b
减少了回溯。
b(w+)[^w=]*=
更精确地匹配你的"言语表达"。例如,它将与abc !@# = def
中的abc
相匹配。
- CCD_ 7在CCD_ 8和CCD_
w
匹配非单词字符W
匹配的字符不是单词字符s
与空白字符匹配- CCD_ 13匹配除CCD_ 14之外的非单词字符
Jack的答案可能是最好的,但我无法理解它是如何工作的。我喜欢把东西分解成小块。
use warnings;
use strict;
my @strings = ( "abc def = ghi",
"abc def ghi = jkl",
"abc def ghi=jkl mno"
);
#
foreach (@strings) {
my $last = get_last($_);
print "$lastn";
}
sub get_last {
my $string = shift;
# group things as left side or right side
my $left_side;
my $right_side;
if ($string =~ /(.*)=(.*)/) {
$left_side = $1;
$right_side = $2;
}
# split things according to whitespace and store in an array
my @left_side = split (/s+/, $left_side);
# return the last element of that array
return $left_side[-1];
}
您也不需要正则表达式。您可以:
split
/s*=s*/
上的第一个字符串- 获取结果数组的第一个元素(即等号之前的所有内容(右端去掉空白))
split
来自/s+/
上步骤2的字符串- 取步骤3中得到的数组的最后一个元素
换句话说:
use strict;
use warnings;
my $str1 = "abc def = ghi";
my $str2 = "abc def ghi = jkl";
my $str3 = "abc def ghi=jkl mno";
sub grab_target{
my $str = shift;
return (split(/s+/, (split(/s*=s*/, $str))[0]))[-1];
}
foreach my $str ($str1, $str2, $str3){
print grab_target $str;
print "n";
}
结果输出为:
def
ghi
ghi