正则表达式捕获模式的最后一次出现

时间:2015-02-05 17:22:25

标签: regex perl

我最后一次尝试了几种方法,但它们没有用。以下是我的情况,

abc def = ghi
abc def ghi = jkl
abc def ghi=jkl mno

对于第一行,我的捕获目标是" def"。对于第二行,我的捕获目标是" ghi",对于第3行,我的捕获目标是" ghi"。目标可以口头表达为"等号前的最后一个单词"。

Perl的正则表达式应该如何?

4 个答案:

答案 0 :(得分:8)

你可以使用这种模式

(\w+)(?=\s*=)

Demo

(               # 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

答案 1 :(得分:3)

\b(\w+)\s*=就足以满足您的示例。它匹配一个单词,可选地紧跟在空格后面,紧接着是=\b会减少回溯。

\b(\w+)[^\w=]*=更精确地符合您的“口头表达”。例如,它将匹配abc中的abc !@# = def

  • \b匹配\w\W
  • \w匹配非单词字符。
  • \W匹配一个不是单词字符的字符。
  • \s匹配空格字符。
  • [^\w=]匹配=以外的非单词字符。

答案 2 :(得分:1)

杰克的回答可能是最好的,但我无法理解它是如何运作的。我喜欢将事情分解成更小的块。

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 "$last\n";
}

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];
}

答案 3 :(得分:0)

你也不需要正则表达式。你可以:

  • 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