2017-05-26 16 views
3

matcherをJavaで使用する動作が不思議です。Javaが正規表現を使用して文字列内の値を検索

私はコンパイルしたパターンを持っていますが、マッチャーの結果を実行すると、なぜ特定の値が欠けているのか理解できません。

マイコード:

String str = "star wars"; 
Pattern p = Pattern.compile("star war|Star War|Starwars|star wars|star wars|pirates of the caribbean|long strage trip|drone|snatched (2017)"); 
Matcher matcher = p.matcher(str); 
while (matcher.find()) { 
     System.out.println("\nRegex : " matcher.group()); 
    } 

私はそれが私のパターンであるように右である「星の戦争」で打撃を受けます。

しかし、私はヒットとして「スターウォーズ」を取得しないと、なぜ私のパターンの一部であるか分からない。

+3

「勝ち」にマッチし、残りはチェックされていない交互のグループの最初の選択肢。 「星の戦争」が一致すると、テキストが消費され、それ以上のパスはありません。それは期待される。どのような振る舞いが必要ですか? –

+0

すべてのヒットを返す方法はありますか? –

+3

長いパターンの交互パターンではなく、パターンごとにパターンを個別にチェックする必要があります。 – NAMS

答えて

2

NFA正規表現のalternationが「熱心」である、つまり最初の試合が勝利し、残りの代替案がテストされていないため、動作が期待されます。また、正規表現エンジンが消費パターンで一致するものを見つけたら(消費パターンであり、lookahead/lookbehind/word boundary/anchorのようなゼロ幅のアサーションではない)、インデックスは最後まで進められますその位置から一致および次の一致が検索される。

最初のstar warブランチが一致すると、star warsの正規表現インデックスが最後のsの前にあるため一致する方法がありません。

最も簡単な方法は、ループしているだけで、文字列は、あなたがチェック対象の文字列が含まれているかどうかを確認、:

String str = "star wars"; 
String[] arr = {"star war","Star War","Starwars","star wars","pirates of the caribbean","long strage trip","drone","snatched (2017)"}; 
for(String s: arr){ 
    if(str.contains(s)) 
     System.out.println(s); 
} 

ところでJava demo

を参照してください、あなたの正規表現はsnatched (2017)が含まれており、それがありません()と一致しません。一致するのはsnatched 2017のみです。リテラルカッコを一致させるには、()をエスケープする必要があります。私はまた、star warsの二重引用符を削除しました。あなたの正規表現を構築するための

+0

このアプローチはさしかし、 'AI'などの映画の問題を避けるために、文字列を' | 'に分割し、' str'と完全に一致させる必要があります。 – steffen

+0

@steffen:素早く配列を作成するために '\ |'で分割します。私は最良の方法は 'String [] arr = {" term1 "、" term2 "、" etc。 "};'で通常通り定義することだと思います。注記私は二重引用符を削除していない、私はそれらが設計時に提供されると思います。 –

+0

答えを編集して、検索用語の配列を定義する方法を示した。 '' \\ | ''で分割するとハッキーです。 –

0

あなたはMatcher.matches()を使用するか、^$を追加する必要がありますので、全体の入力シーケンスを一致させたい:

Pattern p = Pattern.compile("^(star war|Star War|Starwars|star wars|" 
     + "star wars|pirates of the caribbean)$"); 

Regex : star wars 

を出力します。しかし、私は@NAMSに同意:しないでくださいこのような正規表現を構築してください。

1

より良い方法は、次のようになります:

String pattern = "[Ss]tar[\\s]{0,1}[Ww]ar[s]{0,1}"; 

は内訳:

  • [SS]:それは最初の位置にSまたはSのいずれかに一致します
  • \ s:スペースの表現
  • {0,1}

    String pattern = "[Ss]tar[\\s]?[Ww]ar[s]?"; 
    
    • :直前の文字(または設定)が0〜1回

    代替があるからマッチするのだろうか?:直前の文字(または設定)が参照、まったく

詳細については、一度か照合されますhttps://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

編集1:固定タイプミス(\s - >\\s)。ありがとう、@ eugene。

+0

'[\ s]は{0,1}'本当にあるべき '\\ sは+'多くのスペースがあるかもしれないおそらく – Eugene

+0

ユージン:* 0回以上にマッチさせるような。 {0,1}を使うことで、0回または1回だけ一致すると言います。 – luizfzs

+0

@Eugene - '\\ s *'は「スターウォーズ」のようなものも合わせることができます。 – marklark

関連する問題