2010-03-24 80 views
1

我想正則表達式來有效的輸入匹配到Tags輸入字段具有以下屬性:如何改善此正則表達式?

  • 1-5標籤
  • 每個標籤長
  • 有效的標籤字符是1-30個字符[ A-ZA-Z0-9-]
  • 輸入和標籤可以通過空白

的任何量例如被分離:

有效期:標籤1標籤2標籤3,用破折號TAG4與 - 更多的破折號tAaG5與 - 混合大小寫

這裏是我迄今爲止 - 它似乎工作,但我很感興趣怎麼可以簡化或者如果它有任何重大缺陷:

\s*[a-zA-Z0-9-]{1,30}(\s+[a-zA-Z0-9-]{1,30}){0,4}\s* 

// that is: 
\s*       // match all beginning whitespace 
[a-zA-Z0-9-]{1,30}   // match the first tag 
(\s+[a-zA-Z0-9-]{1,30}){0,4} // match all subsequent tags 
\s*       // match all ending whitespace 

預處理的輸入,使空白問題容易不是一個選項(如修剪或添加空間)。

如果它很重要,這將用於JavaScript。任何建議,將不勝感激,謝謝!

回答

3

您可以簡化它有點像這樣:

^(?:(?:^|\s+)[a-zA-Z0-9-]{1,30}){1,5}\s*$ 

(?:)語法是一個非捕獲組,我認爲應該提高性能,當你不需要羣體本身。

然後訣竅就是這樣的說法:

(?:^|\s+) 

由於插入符,這將匹配行,或空白的一個或多個字符的開始。

更新:這在我的測試中完美地工作,並且確實有更少的冗餘代碼。但是,我只是使用benchmarking in Regex Hero來發現您的原始正則表達式實際上更快。這可能是因爲我的造成了更多的回溯。

更新#2:我發現,完成同樣的事情的另一種方式,我認爲:

^(?:\s*[a-zA-Z0-9-]{1,30}){1,5}\s*$ 

我意識到,我是過於賣力。 \s*匹配0個或多個空格,這意味着它可以用於單個標籤。但是...它可以用於2-5個標籤,因爲這個空間不在你的角色類[ ]中。事實上它失敗了6個標籤,因爲它應該。這意味着這是一個更具前瞻性的正則表達式,具有更少的回溯,更好的性能和更少的冗餘。

UPDATE#3:

我在我的方式看到錯誤。這應該會更好。

^(?:\s*[a-zA-Z0-9-]{1,30}\b){1,5}\s*$ 

剛剛過去)之前把\b將斷言單詞邊界。這允許1-30字符長度規則再次正常工作。

+0

這是一個整潔的網站 - 感謝參考 – 2010-03-24 22:56:53

+0

@Michael - 不客氣。並檢查我的第二次嘗試在這裏。它更簡單,我認爲表現與你的第一個表達大致相同。 – 2010-03-24 23:12:37

+1

@Steve:我感謝你的額外努力 - 不幸的是,最新的正則表達式並不限制在30個字符/每個 - 即。它匹配一個40char標籤 – 2010-03-24 23:15:26

1

你的RE看起來像是在做你正在做的事情。我可能會推薦使用而不是,但在這種情況下,只需將空白處的輸入拆分爲數組,然後單獨驗證數組中的每個值。

RE比較涼爽,但有時,他們不是來完成這項工作:)

+0

我聽到你 - 在服務器上,這是我可能最終做的事情。但是,將正則表達式插入到ASP.NET MVC模型驗證引擎中非常簡單,我現在想要堅持使用它 – 2010-03-24 22:27:39

+0

或者您可以編寫自定義驗證來完成分割。 – 2010-03-24 22:30:37

0

\w可能取代a-zA-Z0-9最好的方式,但它也包含_如果這是好的。

您可能還可以打破它多一點這樣的:

(\s*[a-zA-Z0-9-]{1,30}){0,5} 

如果你總是保證有空格分隔的標籤。

+2

雖然這不符合60,90,120個字符的單個標籤嗎? – 2010-03-24 22:31:27

+0

是的,你是對的,邁克爾,這不符合你的要求。 – Pindatjuh 2010-03-24 22:34:41

+0

是的,這就是我不清楚的是,標籤是否總會被ws分開。如果不是,我不確定如何確定如何處理60個字符的長字符串?也許發佈一個例子會有所幫助。 – 2010-03-24 22:36:55

0

你可以縮短到像

([a-zA-Z0-9-]{1,30}\s*){1,5}

我總是喜歡讓我的正則表達式更簡潔(它不會影響性能)。

+0

這是不是會匹配60,90,120個字符的單個標籤? – 2010-03-24 22:34:03

+0

此正則表達式不起作用。由於'\ s'處的'*','{1,30}'字段失敗。 – Pindatjuh 2010-03-24 22:35:25

+0

非常真實。 :( – Ben 2010-03-24 22:43:01

2

性能方面,可以優化(提高)這樣說:

^(?:\s+[a-zA-Z0-9]{1,30}){1,5}\s*$ 

並在前面加一個空格,測試正則表達式之前。

^ 
(?: // don't keep track of groups 
\s+ // first (necessairy whitespace) or between 
    [a-zA-Z0-9-]{1,30} // unchanged 
){1,5} // 1 to 5 tags 
\s*$ 
+0

+1對於很好的解釋與評論 - 我剛剛瞭解到一些關於組跟蹤提示。我認爲你仍然需要處理破折號( - ),但... – 2010-03-24 22:36:46

+0

謝謝,下次我會複製和粘貼,而不是retype。更正的錯字 – Pindatjuh 2010-03-24 22:38:03

+0

我喜歡這個 - 謝謝 - 不幸的是,我無法預處理輸入,例如增加一個空格 – 2010-03-24 22:43:37

0

你不會改進。你所做的任何事情都會減少閱讀的長度,而正則表達式在這方面不需要任何幫助。 ;)

這就是說,無論如何,你的正則表達式需要更復雜。如書面所述,它無法確保標籤名稱不以連字符開頭或結尾,或者包含兩個或更多個連續的連字符。單個標籤的正則表達式將需要像這樣被構建:

[A-Za-z0-9]+(?:-[A-Za-z0-9]+)* 

然後將基準正則表達式匹配最多五個標籤將

[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*(?:\s+[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*){0,4} 

...但是,這並不強制執行最大標籤長度。我認爲這樣做最簡單的方法是把你原來的正則表達式在先行:

/^\s* 
(?=[A-Za-z0-9-]{1,30}(\s+[A-Za-z0-9-]{1,30}){0,4}\s*$) 
(?:[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*\s*)+$ 
/

先行強制標籤長度以及對以空格分隔的五個標籤的整體結構。然後,主體只需執行各個標籤的結構。

我可以通過將a-z留在字符類別之外並添加i修飾符來縮短正則表達式的位數。我沒有這樣做,因爲你談論了在ASP.NET驗證器中使用正則表達式,並且據我所知,他們不允許使用正則表達式修飾符。而且,由於JavaScript不支持(?i)內聯修飾符語法,所以不可能使用不區分大小寫的驗證器正則表達式。如果我誤解了這一點,我希望有人會糾正我。