2013-08-03 71 views
6

我一直在爲這些亂七八糟的東西而努力。我記得一位講師曾經告訴過我們,如果你有一個問題需要你使用正則表達式來解決它,你現在實際上有兩個問題。用戶名不能包含重複的下劃線或句點

那麼,我當然同意這一點。正則表達式是我們不經常使用的東西,但是當我們喜歡閱讀某種外來語言時(對我來說無論如何)...我想我會決定去閱讀本書並進一步閱讀。

我的挑戰是這一點,我需要驗證基於以下條件的用戶名:(.

  1. 可包含字母,上部和下部
  2. 可以包含數字
  3. 可以含有周期)和下劃線(_
  4. 週期和下劃線不能連續,即__..不允許,但._._將是有效的。

到目前爲止,我有以下的最多20個字符:^[a-zA-Z_.]{0,20}$但當然可以重複下劃線和句點。

現在,我可能會做這一切錯誤開始與有效字符和最大長度的設置。我一直在嘗試(不成功)創建一些環視或後臺或搜索週期(.)和下劃線(_)的無效重複的內容,但不確定將此要求分解爲正則表達式解決方案的方法或方法是。

任何人都可以幫助建議/替代方法或指向正確的方向嗎?

+0

你忘了你的正則表達式中的數字;另外,你只是想允許ASCII字母/數字?你使用的是哪種正則表達式引擎(順便說一下,這是StackOverflow上所有正則表達式問題的必要信息)? –

+3

正則表達式仍然是要走的路。如果使用它們,解析字符串所需的所有知識都在正則表達式中。如果你不使用它們,知識就會遍佈整個地方,並且你有一堆for循環,大量的字符串操作和數百萬的邊界情況,你可能會忘記實現,所產生的代碼甚至是buggier,更難閱讀。不要讓講師勸阻你,如果你對任何事情都不夠了解,那很難,如果你知道的夠多,這很容易。 – escitalopram

+0

啊是好的發現我輸入錯誤的應該是^ [a-zA-Z0-9_。]這對於確保所有有效的ASCII字符是足夠好的,但是我正在努力處理需求#4而不分裂成2個表達式。在正則表達式引擎方面,我驗證了客戶端(Javascript)和服務器端ASP.NET 4.5 – SpaceKat

回答

8

這個人是一個你需要的:

^(?:[a-zA-Z0-9]|([._])(?!\1)){5,20}$ 

Regular expression visualization

Edit live on Debuggex

你可以擁有的東西它匹配here演示。


「要麼一個alphanum炭([a-zA-Z0-9]),或(|)一個點或一個下劃線([._]),而後面沒有本身((?!\1)),和從5到20倍( {5,20})「。

  1. (?:X)簡單地是一個非捕獲組,即不能引用它之後使用\1$1?1語法。

  2. (?!X)被稱爲負向預測,即字面意義上的「其後沒有X」。

  3. \1指的是第一個捕獲組。由於第一組(?:...){5,20}已被設置爲非捕獲(參見#1),因此第一捕獲組爲([._])

  4. {X,Y}意味着從X到Y倍,您可以根據需要進行更改。

+2

這可能是最快的解決方案。 –

+0

我喜歡所有提供的答案,但對於此解決方案而言,我認爲這是迄今爲止最優雅的解決方案。當然,一旦解釋這一切都很有意義:)這是一個令人愉快的挑戰,謝謝大家的貢獻! – SpaceKat

6

您可以使用兩種negative lookahead assertions此:

^(?!.*__)(?!.*\.\.)[0-9a-zA-Z_.]{0,20}$ 

說明:

(?! # Assert that it's impossible to match the following regex here: 
.* # Any number of characters 
__ # followed by two underscores in a row 
) # End of lookahead 

根據您的要求,並在你的正則表達式引擎,可以與[\w.]取代[0-9A-Za-z_.]

@ sp00n提出了一個很好的點:您可以先行斷言合併爲一個:

^(?!.*(?:__|\.\.))[0-9a-zA-Z_.]{0,20}$ 

這可能是有點更有效,但有點難以閱讀。

+2

爲什麼不使用帶有OR的單個負向前視?你的情況正在經歷整個輸入3次。 – sp00m

+0

@ sp00m:好點。我編輯了我的答案。我不確定這會對性能產生多大影響,但它肯定是一個很好的選擇。 –

6

不要試圖將其推入單個正則表達式中。您的單一正則表達式對於#4以外的所有條件都可以正常工作。要做#4,只是做一個正則表達式,匹配無效的用戶名,並拒絕用戶名,如果匹配。例如(在僞代碼):

if username.matches("^[a-zA-Z_.]{0,20}$") and !username.matches("__|\\.\\.") { 
    /* accept username */ 
} 
+0

(不完全確定你的意思是「不能連續」,因爲你說'..'是可以的,但這個例子無論如何都是說明性的)。 – nneonneo

+0

如果這應該是Java,那就錯了。 –

+0

'..'不行。在原始文章中有(缺少)格式問題。 –