2011-02-08 32 views
1

我試圖寫一個正則表達式,允許單個連字符和單個空格只在單詞內但不在單詞的開頭或結尾。PHP的preg_match與正則表達式:只有單個連字符和單詞之間的空格繼續

,我想我有這個從answer昨天我排序,但我才意識到有小錯誤,我也不太明白,

爲什麼它不會接受像輸入,

'forum-category-b forum-category-a' 
'forum-category-b Counter-terrorism' 
'forum-category-a Preventing' 
'forum-category-a Preventing Violent' 
'forum-category-a International-Research-and-Publications' 
'International-Research-and-Publications forum-category-b forum-category-a' 

但需要,

'forum-category-b' 
'Counter-terrorism forum-category-a' 
'Preventing forum-category-a' 
'Preventing Violent forum-category-a' 
'International-Research-and-Publications forum-category-b' 

這是爲什麼?我該如何解決它?它下面是與初始試驗中的正則表達式,但理想地應該接受上述所有的組合輸入,

$aWords = array(
    'a', 
    '---stack---over---flow---', 
    ' stack over flow', 
    'stack-over-flow', 
    'stack over flow', 
    'stacoverflow' 
); 

foreach($aWords as $sWord) { 
    if (preg_match('/^(\w+([\s-]\w+)?)+$/', $sWord)) { 
     echo 'pass: ' . $sWord . "\n"; 
    } else { 
     echo 'fail: ' . $sWord . "\n"; 
    } 
} 

接受/拒絕輸入等這些下面,

---stack---over---flow--- 
stack-over-flow- stack-over-flow2 
    stack over flow 

感謝。

+0

您可能想了解Dash標點符號的'\ p {Pd}'屬性。 – tchrist

回答

1

你的模式不會做你想做的。讓我們把它分解開:

^(\w+([\s-]\w+)?)+$ 

它匹配只包含圖形的一個或多個序列串:

\w+([\s-]\w+)? 

...這是單詞字符序列,由一個其他然後任選單詞字符序列,由一個空格或破折號字符分隔。

換句話說,你的模式將搜索字符串一樣:

xxx-xxxyyy-yyyzzz zzz 

...但你的意圖編寫會發現這樣一個規律:

xxx-xxxxxx-xxxxxx yyy 

在你的例子,這一個匹配:

Counter-terrorism forum-category-a 

...但它被解釋爲按以下順序:

(Counter(-terroris)) (m(foru)) (m(-categor) (y(-a)) 

正如你所看到的,該模式並沒有真正找到你正在尋找的話。

這個實例不匹配:

forum-category-a Preventing Violent 

...由於圖案不能形成的「字字符,空間或劃線,文字字符」基團,當它遇到一個字字符,接着空間或破折號:

(forum(-categor)) (y(-a)) <Mismatch: Found " " but expected "\w"> 

如果你想添加一個字符「論壇類-A」,說:「論壇類-AX」,它會再次匹配,因爲它可以在「斧頭」分裂:

(forum(-categor)) (y(-a)) (x(Preventin)) (g(Violent)) 

你是什麼真正感興趣的是像

^(\w+(-\w+)*)(\s\w+(-\w+)*)*$ 

的模式......它會發現,可能包含破折號的話,用空格分隔的序列:

(forum(-category)(-a)) (Preventing) (Violent) 

順便說一句,我測試了這個使用Python腳本,並試圖匹配您的模式與示例字符串「國際研究和出版物論壇-category-B論壇類別-A」,正則表達式引擎似乎陷入無限循環......

import re 
expr = re.compile(r'^(\w+([\s-]\w+)?)+$') 
expr.match('International-Research-and-Publications forum-category-b forum-category-a') 
+0

非常感謝你!你救了我的命!我在另一個正則表達式中只添加了字母數字字符 -/^ [a-zA-Z0-9 \ - \ s] + $/lol謝謝! – laukok

+0

感謝您的編輯。 awww Python !!!它適用於PHP。怎麼來的!???哪種語言有bug? sign ....我猜這個正則表達式是不正確的 -/^(\ w +([\ s - ] \ w +)?)+ $ /! – laukok

+0

我想這與Python vs PHP無關,但它是正在使用的正則表達式引擎的實現細節。也許PHP的PCRE引擎比Python的SRE引擎有更嚴格的循環檢測。問題實際上是你的正則表達式模式,另見http://www.regular-expressions.info/catastrophic.html –

0

你圖案的部分([\s-]\w+)?是問題所在。它只允許一次重複(尾隨?)。嘗試將最後的?更改爲*,看看是否有幫助。

不,我仍然認爲這是問題所在。原始模式正在尋找重複1次以上的「單詞」或「單詞[space_hyphen]單詞」。這很奇怪,因爲這種模式應該屬於另一場比賽。但是切換問號worked for me

0

應該只有一個回答這個問題:

/^((?<=\w)[ -]\w|[^ -])+$/

只有一個規則\w[ -]\w和多數民衆贊成在它。而其上的每個字符基礎上的粒度爲,並且不能爲其他。爲其餘的添加[^ - ]。

相關問題