[英]Regex to match and limit character classes
我不確定使用Regex是否可行,但我希望能夠根據不同的字符限制允許的下划線數量。 這是為了將瘋狂的通配符限制限制為用Java編寫的搜索引擎。
起始字符是字母數字。 但是如果有更多的下划線而不是前面的字符,我基本上想要一個匹配。 所以
BA_會很好但是BA___會匹配正則表達式並且會被踢出查詢解析器。
這可能使用正則表達式嗎?
是的,你可以做到。 : 只有當下划線少於字母時,此模式才會成功 :
^(?:[A-Z](?=[A-Z]*(\\1?+_)))*+[A-Z]+\\1?$
否定版本:
^(?:[A-Z](?=[A-Z]*(\\1?+_)))*\\1?_*$
我們的想法是重復一個包含對自身的反向引用+下划線的捕獲組。 在每次重復時,捕獲組都在增長。 ^(?:[AZ](?=[AZ]*+(\\\\1?+_)))*+
將匹配具有對應下划線的所有字母。 您只需添加[AZ]+
以確保有更多字母,並使用\\\\1?
完成您的模式\\\\1?
包含所有下划線(我將其設為可選,以防根本沒有下划線)。
請注意,如果在第一個模式中將[AZ]+
替換為[AZ]{n}
,則可以精確設置字母和下划線之間的字符數差異。
為了給出一個更好的想法,我將嘗試逐步描述它如何與字符串ABC--
(因為不可能將下划線以粗體顯示,我使用連字符代替):
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$ ABC-- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*+[A-Z]+\1?$
示例: ABC---
和模式: ^(?:[AZ](?=[AZ]*(\\1?+-)))*[AZ]+\\1?$
ABC--- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*[A-Z]+\1?$ ABC--- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*[A-Z]+\1?$ ABC--- ^(?:[A-Z](?=[A-Z]*(\1?+-)))*[A-Z]+\1?$
問題:捕獲組中有多少個連字符?
答:總是三個!
如果重復的非捕獲組返回一個字母,捕獲組總是包含三個連字符(正如最后一次正則表達式引擎讀取捕獲組)。這是違反直覺的,但是合乎邏輯的。
$pattern = <<<'EOD'
~
(?(DEFINE)
(?<neutral> (?: _ \g<neutral>?+ [A-Z] | [A-Z] \g<neutral>?+ _ )+ )
)
\A (?: \g<neutral> | _ )+ \z
~x
EOD;
var_dump(preg_match($pattern, '____ABC_DEF___'));
Robby Pond在評論中問我如何找到下划線比字母更多的字符串(所有這些都不是下划線) 。 顯然,最好的方法是計算下划線的數量並與字符串長度進行比較。 但是關於完整的正則表達式解決方案,由於模式需要使用遞歸功能,因此無法使用Java構建模式。 例如,你可以用PHP做到這一點:
$pattern = <<<'EOD' ~ (?(DEFINE) (?<neutral> (?: _ \\g<neutral>?+ [AZ] | [AZ] \\g<neutral>?+ _ )+ ) ) \\A (?: \\g<neutral> | _ )+ \\z ~x EOD; var_dump(preg_match($pattern, '____ABC_DEF___'));
它在單數正則表達式中是不可能的。
i)需要實現邏輯以獲得下划線之前的字符數(應該編寫正則表達式以在下划線之前獲得字符)。
ii)並驗證結果(字符數 - 1)=所遵循的分號數(正則表達式返回下划線后跟字符)。
編輯:當! 我剛剛注意到你需要這個用於java。 無論如何......如果來自.Net世界的人偶然發現這篇文章,我就把它留在這里。
如果您使用.Net,則可以使用平衡組 :
^(?:(?<letter>[^_])|(?<-letter>_))*(?(letter)(?=)|(?!))$
.net正則表達式引擎能夠維護捕獲的組中的所有捕獲模式。 在其他類型中,捕獲的組將始終包含最后匹配的模式,但在.net中,所有先前的匹配都包含在捕獲集合中供您使用。 此外,.net引擎還能夠使用?<group-name>
, ?<-group-name>
構造來推送和彈出捕獲的組的堆棧。 這兩個方便的結構可用於匹配paranthesis對等。
在上面的正則表達式中,引擎從字符串的開頭開始,並嘗試匹配“_”以外的任何內容。 這當然可以改為適合你的任何東西(例如[AZ][az]
)。 交替基本上意味着匹配[^\\_]
或[\\_]
並且這樣做可以從捕獲的組中推送或彈出。
正則表達式的后半部分是條件(?(group-name)true|false)
。 它基本上說,如果該組仍然存在(比彈出更多推送),那么執行true部分,如果不執行false部分。 使模式匹配的最簡單方法是使用空的正向前看: (?=)
並且使其失敗的最簡單方法是(?!)
,這是一個負前瞻。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.