2011-06-23 43 views
1

我想用REGEX驗證PHP中的輸入。我想檢查輸入中是否有%s字符組,並且它只出現一次。否則,該規則應該失敗。正則表達式/ PHP檢查字符組是否只出現一次

這是我已經試過:

preg_match('|^[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$|u', $value);(也有除此之外其他一些規則,我已經試過了(%s){1}的一部分,它不工作)。

我相信這是一個非常簡單的解決方案,但我沒有真正進入REGEX的...謝謝你的幫助!

+0

鑑於你自己的答案,我建議這個問題的標題是不正確的。 – Johnsyweb

+0

更改標題以反映我的答案。 – linkyndy

回答

4

如果我理解你的問題,你需要一個積極的前瞻。向前看將導致表達式僅在找到單個%s時才匹配。

preg_match('|^(?=[^%s].*?[%s][^%s]*$)[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$|u', $value); 

我將解釋每一部分如何工作

^(?=[^%s].*?[%s][^%s]*$)是一個零寬度斷言 - (?=regex)積極前瞻 - (這意味着它必須匹配,但不「吃」的任何字符)。這意味着整條生產線只能有1 %s

[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$正則表達式的其餘部分也查看整個字符串,並確保整個字符串只包含字符類中的字符(如原始正則表達式)。

+0

你能解釋一下你添加的代碼是什麼嗎?這似乎很複雜:) – linkyndy

+0

@linkyndy,我已經添加了一個解釋。如果需要,請不要猶豫,要求進一步澄清。祝你好運。 –

+0

感謝您澄清。現在看起來更清楚了,但我仍然認爲我需要REGEX的練習。因此我現在要堅持'substr_count()'解決方案。再次感謝! – linkyndy

1

或者,您可以使用preg_match_all與您的模式,並檢查匹配的數量。如果它是1,那麼你沒事 - 像這樣:

$result = (preg_match_all('|^[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$|u', $value) == 1) 
0

如果你不是「進入」正則表達式,爲什麼不用PHP來解決這個問題?

給內建的strpos()的一個調用會告訴你該字符串是否匹配。第二個電話會告訴你它是否出現多次。

這將更容易讓您閱讀併爲其他人維護。

+0

我的整個驗證由正則表達式組成,我希望每條規則都在一行之內,而不是分散在多個代碼塊中。 – linkyndy

+0

這就是*功能*的用途! – Johnsyweb

1

試試這個:

'|^(?=(?:(?!%s).)*%s(?:(?!%s).)*$)[0-9_\s:;,.?!()\p{L}-]+$|u' 

方括號內的(%s){1}序列可能不會做你認爲是這樣,不過沒關係,解決的辦法是比較複雜的。實際上,{1}絕不應該出現在正則表達式的任何地方。它並不能確保只有一件東西,正如許多人所假設的那樣。事實上,它不會做什麼;這是純粹的混亂。


EDIT(在回答評論):爲了確保只有特定序列的一個存在於一個字符串,你必須積極地檢查每一個單個字符,它歸類爲任一部分-OF- %s不是部分-。爲此,(?:(?!%s).)*一次只消耗一個字符,之後負向超前已確認該字符不是%s的開始。

當前瞻表達式的那部分退出匹配時,字符串中的下一個事物必須是%s。然後第二個(?:(?!%s).)*$開始進行確認,直到字符串結束爲止,不再有%s序列。

不要忘記,前瞻表達式必須在兩端都錨定爲。因爲lookahead是主正則表達式啓動後的第一個主播,所以您不需要再添加其他^。但前瞻必須以自己的$結尾。

+0

謝謝,但是你能解釋一下,在我現有的正則表達式之前,所有這些順序是什麼?我認爲這將是一個簡單的解決方案,但看起來非常複雜。 – linkyndy

+0

好的,我在答案中加了一個解釋。 –

+0

哦,所以這不是很容易,但我想我設法瞭解這個想法。感謝澄清。我肯定需要REGEX的更多練習......但是在那之前,我會堅持用'substr_count()'的解決方案。 – linkyndy

2

我設法用PHP的substr_count()功能來做到這一點,以下Johnsyweb建議使用替代的方式來進行驗證和因爲正則表達式的建議似乎相當複雜。

再次感謝您!

+1

這比我的回答好得多!我不是一名PHP開發人員,因爲它被標記爲[正則表達式],所以我偶然發現了這個問題。 – Johnsyweb

相關問題