2015-02-05 57 views
1

我嘗試了幾種最後一次出現的方式,但它們不起作用。以下是我的情況,捕獲最後一次出現的模式的正則表達式

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

對於第一行,我的捕獲目標是「def」。對於第二行,我的捕獲目標是「ghi」,對於第三行,我的捕獲目標是「ghi」。目標可以口頭表達爲「等號前最後一次出現的單詞」。

Perl的正則表達式應該是什麼樣子?

回答

9

,你可以使用這個模式

(\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 
+0

這裏預見的唯一功能是減慢匹配。 – ikegami 2015-02-05 17:51:11

+0

我使用後視,因爲我認爲它是從「=」號後面找到最接近的單詞。但後視對我來說不起作用。 – Allen 2015-02-06 08:15:13

+0

@Allen,你不能在這裏使用lookbehind,因爲lookbehinds匹配的長度必須獨立於輸入。即使它確實有效,使用lookbeind也會讓事情變得緩慢。我很失望你接受了這個不合理的解決方案 – ikegami 2015-02-06 16:58:50

2

\b(\w+)\s*=就能滿足你的例子。它匹配一個字,緊隨其後的是空格,緊接着是=\b減少回溯。

\b(\w+)[^\w=]*=更精確地匹配您的「語言表達」。例如,它將在abc [email protected]# = def中匹配abc

  • \b一個\w\W之間的匹配。
  • \w匹配一個非單詞字符。
  • \W匹配不是單詞字符的字符。
  • \s匹配一個空白字符。
  • [^\w=]與除=以外的非單詞字符匹配。
+0

我認爲[^ \ w =]的含義與字符和「=」符號不符。 – Allen 2015-02-06 08:22:21

+0

@Allen,你說的沒錯,但你可能會說「'[\ w =]'不會游泳」。說它沒有做的一件事是無用的,所以我說它做了什麼(匹配一個不是字符字符而不是'='的字符)。 – ikegami 2015-02-06 17:02:41

0

你也不需要正則表達式。您可以:

  • split/\s*=\s*/
  • 搶所得數組的第一個元素
  • split(即所有之前等號(含空格剝離右端)的東西)的第一個字符串從步驟2的/\s+/
  • 字符串取所得陣列的最後一個元素從步驟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 
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]; 
} 
+0

是的,它有點緊湊......實質上,直接從split分割的數組中獲取索引元素 - 即split(/ \ s * = \ s * /,$ str)[0]'是一個語法錯誤。所以,你必須將'split'包裝在括號中,如下所示:'(split(/ \ s * = \ s * /,$ str))[0]'。其餘部分將該元素分割到'/ \ s + /'上,並抓取該結果數組的最後一個元素。希望能夠解決問題。你的寫作也很好。 :) – 2015-02-06 18:36:42

相關問題