2011-10-29 64 views
4

我試圖匹配從最後一個項目壁櫥到最後一個字。perl正則表達式匹配最接近

例如,最接近b鍵狗

「abcbdog」

應該是 「bdog」

但相反我得到 「bcbdog」

我怎樣才能僅從匹配「狗」之前的最後一次出現「b」

這裏是我當前的正則表達式:

/b.*?dog/si 

謝謝!

回答

7

的正則表達式要從左向右走,但是你想從右邊轉到左邊,這樣只是扭轉你的字符串,扭轉你的模式和反向匹配:

my $search_this = 'abcbdog'; 
my $item_name = 'dog'; 
my $find_closest = 'b'; 

my $pattern = reverse($item_name) 
      . '.*?' 
      . reverse($find_closest); 

my $reversed  = reverse($search_this); 
$reversed  =~ /$pattern/si; 
my $what_matched = reverse($&); 
print "$what_matched\n"; 
# prints bdog 
+0

真棒。非常狡猾。非常感謝。 – srchulo

+0

@TLP:是否爲你編輯工作?我認爲人們也會閱讀這些評論,但有時我認爲是錯誤的。 –

+0

@ muistooshort它看起來是正確的。 – TLP

4

試試這個:

/b[^b]*dog/si 

比賽b,則任何不是一個b(包括無),然後dog

+0

真棒!這適用於我給出的例子。我現在唯一的問題是現在當我用變量將它放入我的腳本時,如下所示:($ string =〜/ $ item_name([^ $ item_name] * $ match)/ si)它將括號中的$ item_name變量是字面意思,它不會匹配:/ – srchulo

+6

@srchulo您要求爲文字字符,而不是變量的解決方案。如果你發現自己提出了錯誤的問題,你應該編輯你的問題。 – TLP

1

TIMTOWTDI:

這方法甚至可以通過字符串找到多個匹配項,或者如果開始或結束字更常見,可能會進行優化。 編輯:現在使用零寬度匹配來避免刪除然後添加開始和結束字符串。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use v5.10; #say 

my $string = 'abcbdog'; 
my $start = 'b'; 
my $end = 'dog'; 

my @found = 
    grep { s/(?<=$end).*// } 
    split(/(?=$start)/, $string); 

say for @found; 
+0

+1不錯的使用拆分。儘管你可以使用負面預覽而不是'map':'/(?= $ start)/'。 – TLP

+0

@TLP,是的,似乎工作。雖然我相信你打算稱之爲「積極向前」。 –

+0

爲什麼是,我做到了。 =)至少我有一半是正確的。 – TLP

0

,當你已經不知道什麼是最後一個字符狗在此之前只是工作:

my $str = 'abcbdog'; 

my @r = $str =~ /(.dog)/; 

print @r; 

打印bdog

0

接受的答案似乎有點複雜,如果你只是試圖與最接近的'b'和'狗'相匹配,包括狗,你只需要在你尋找貪婪的術語之前進行比賽。例如:

# First example 
my $string1 = 'abcbdog'; 
if ($string1 =~ /.+(b.*dog)/) { 
    print $1; 
    # Returns 'bdog' 
} 

# Second example, different string, same regex. 
my $string2 = 'abcbmoretextdog'; 
if ($string2 =~ /.+(b.*dog)/) { 
    print $1; 
    # Returns 'bmoretextdog' 
} 

或者我錯過了什麼?如果你想改變捕捉到的字符串來匹配你想要的,只需要移動括號。