2011-06-30 59 views
3

看看下面的例子,有沒有辦法在preg_match_all()中移動/重置搜索指針?

preg_match_all("/(^|-)[a-z]+(-|$)/i", "foo-bar-moo", $matches); 

這(正確)返回下面的比賽,

foo- 
-moo 

但是,我需要生成以下匹配輸出,

foo- 
-bar- 
-moo 

有其實是一種方法來做到這一點?比如說在比賽結束後將搜索指針移回一個字符?

我唯一的想法是把它放在一個while()循環中,刪除每個循環上的匹配,直到找到所有匹配。

謝謝。

編輯:我試圖簡化我的問題,使問題更清晰,但這樣做我似乎已經歪曲了什麼我的問題實際上是。道歉。

基本上我需要一種方法來匹配一個字符串中的一個單詞,其中緊接着的字符或緊隨其後的字符是某個字符,但同時不會捕獲匹配中的這些前導和尾隨字符。

我的印象是你無法做到這一點,所以我決定捕捉前/後的字符,並自己刪除它們。這導致了我上面的問題。

正如Tim Pietzcker指出的那樣,我實際上需要的是lookarounds

因此,對於我上面的例子中,解決方法如下,

preg_match_all('/(?<=^|-)[a-z]+(?=-|$)/', "foo-bar-moo", $result); 
的答案和幫助

,並將其輸出,再

foo 
bar 
moo 

感謝。

+0

你可以讓連字符可選(我認爲這是語法)? ?(^ | - )A-Z] +( - | $)? –

+0

不行,我需要拿起'-'纔可以。 –

回答

1

使用lookaround並將捕獲組放在lookaround表達式中。這可以讓你做一個單一preg_match_all()電話,還是捕捉到- ES(如果存在):

preg_match_all('/(?<=(^|-))([a-z]+)(?=(-|$))/', $subject, $result, PREG_SET_ORDER); 
for ($match = 0; $match < count($result); $match++) { 
    echo $result[$match][1] . $result[$match][2] . $result[$match][3]; 
} 
+0

你先生是一個學者和紳士。在我的問題中的例子是從我的實際問題(對不起)相當抽象,並且周圍的表達式正是我需要解決我的問題。謝謝。 –

0

什麼

preg_match_all("/(^|-)([a-z])+(-|$)/i", "foo-bar-moo", $matches); 

你會得到[富,酒吧,哞。

+0

+1用於分組的創意使用。 – Nightfirecat

+0

除非我錯過了一些東西,這與我的問題中的正則表達式沒有任何不同,並給出了相同的結果? –

1

我想你必須使用preg_match中的offset參數。從0開始,獲得第一場比賽-*[a-z]-*。取matchOffset + matchLength - #dashesAtEnd並將其用作下一個preg_match調用的偏移量。

+0

這是一個選項。但是,我有一大塊內容正在測試中,並且有一個_long_生成的正則表達式。理想情況下,我很樂意將一些東西傳遞給'preg_match_all()',所以我只需要運行一次就可以獲得性能。 –

+0

@Stephen,我認爲preg_match_all將不得不做幾乎相同的事情,除非不減少當前的偏移量。你確定這是一個性能問題嗎? –

+0

@ agent-j:我會做一些基準測試,看看是否多次運行它確實會產生影響。歡呼的建議,但。希望我可以使用它。 –

0

思考你需要:

Array 
(
    [0] => foo- 
    [1] => -bar- 
    [2] => -moo 
) 

但我可以從你更新的問題看,這應該工作以及:

preg_match_all("/(?-)[a-z]+(?-)/i", "foo-bar-moo", $matches); 

echo $matches[0]; 

Array 
(
    [0] => foo 
    [1] => bar 
    [2] => moo 
) 
相關問題