2017-07-27 11 views
1

私は検索の束をやったことがありますが、私は正規表現と私のgoogle-fuはこの例では強くないとしてひどいです。エラーチェック付き正規表現

シナリオ:プッシュ通知で

、我々は9桁のコンテンツIDが含まれているURLを可決しています。

例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

ように見えることができます。 –

+0

は、コンテンツIDの前にタイトル部分の数字をバイパスしますか? – Psest328

+0

https://regex101.com/r/3PamZj/1を参照 –

答えて

1

ここでの基本的な答えは、「{9}限定量を限定的に置き換えて、1回だけ一致する+量指定子を持つ9回の出現と正確に一致します」というパターンが2つあります改善されました。

エスケープされていないドットは、リテラルドットと一致するようにパターンでエスケープする必要があります。

重複するマッチがない場合は、前にキャプチャグループで肯定先読みを使用する必要はありません。キャプチャグループを維持して、.group(1)の値を取得するだけです。

non-capturing group (?:...)はまだ消費するパターンであり、(?:contentId=)は(あなたが(?:を削除し、)場合があります)contentId=に等しいです。

character class内に単一の原子をラップする必要はありません。[\\d]の代わりに\\dを使用してください。その[\\d]は実際には誤解の原因であり、グループ化されていると考えられる人もいれば、シーケンスを角括弧に入れてみるとよいでしょう。[...]は1つの文字に一致します。

だから、あなたのコードは、(1回以上の出現){9} `` + ``と置き換え

 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); 
      } 
     }