2017-07-27 88 views
1

我已經做了一堆搜索,但我很糟糕的正則表達式和我的谷歌福在這種情況下,不強。與錯誤檢查正則表達式

場景:

在推送通知,我們通過包含一個9位數的內容ID的URL。

實例網址:http://www.something.com/foo/bar/Some-title-Goes-here-123456789.html(123456789在此方案中的內容ID)

當前正則表達式來解析內容ID:

public String getContentIdFromPathAndQueryString(String path, String queryString) { 
     String contentId = null; 
     if (StringUtils.isNonEmpty(path)) { 
      Pattern p = Pattern.compile("([\\d]{9})(?=.html)"); 
      Matcher m = p.matcher(path); 
      if (m.find()) { 
       contentId = m.group(); 
      } else if (StringUtils.isNonEmpty(queryString)) { 
       p = Pattern.compile("(?:contentId=)([\\d]{9})(?=.html)"); 
       m = p.matcher(queryString); 
       if (m.find()) { 
        contentId = m.group(); 
       } 
      } 
     } 

     Log.d(LOG_TAG, "Content id " + (contentId == null ? "not found" : (" found - " + contentId))); 
     if (StringUtils.isEmpty(contentId)) { 
      Answers.getInstance().logCustom(new CustomEvent("eid_url") 
        .putCustomAttribute("contentId", "empty") 
        .putCustomAttribute("path", path) 
        .putCustomAttribute("query", queryString)); 
     } 

     return contentId; 
    } 

問題: 這做這項工作,但有一個特定的錯誤我需要考慮的情景。

無論是誰創建推送可能會輸入錯誤的長度的內容ID,我們需要抓住它,所以假設它可以是任意數字的數字......標題也可以包含數字,這是煩人的。內容ID將總是後面跟着「.html」

+0

更換'{9}'和'+'(出現一次或多次)。 –

+0

會在內容ID之前繞過標題部分中的任何數字嗎? – Psest328

+0

查看https://regex101.com/r/3PamZj/1 –

回答

1

雖然這裏的基本答案只是「替換{9}限制量詞匹配正好9次出現與+量詞匹配1+次出現」,有兩種模式可以是改進。

未轉義的點應該在模式中轉義以匹配文字點。

如果您沒有重疊匹配,則無需在捕獲組之前使用正向前視功能,只需保留捕獲組並抓取值即可。

non-capturing group (?:...)仍然是一個耗時圖案,並且(?:contentId=)等於contentId=(您可能除去(?:))。

有沒有必要包裝一個character class內的單個原子,使用\\d而不是[\\d][\\d]實際上是誤解的來源,有些人可能認爲它是一個分組構造,並且可能會嘗試將替代序列放入方括號中,而[...]匹配單個字符。

所以,你的代碼可以像

 Pattern p = Pattern.compile("(\\d+)\\.html");  // No lookahead, + instead of {9} 
     Matcher m = p.matcher(path); 
     if (m.find()) { 
      contentId = m.group(1);      // (1) refers to Group 1 
     } else if (StringUtils.isNonEmpty(queryString)) { 
      p = Pattern.compile("contentId=(\\d+)\\.html"); 
      m = p.matcher(queryString); 
      if (m.find()) { 
       contentId = m.group(1); 
      } 
     }