2015-11-18 10 views
9

正確に2文字(大文字1文字と小文字1文字)と正確に6桁の数字を含む8文字の文字列に一致させる必要がありますが、 。正確にn個の文字とm個の数字が一致する正規表現

だから、基本的には:

  • K82v6686が
  • 3w28E020が
  • 1276eQ900は(長すぎる)失敗するでしょう渡す渡す
  • 98Y78k9kが(3文字)失敗する
  • A09B2197は(失敗するだろう大文字2つ)

文字列に数字、大文字、小文字が含まれていることを確認するための肯定的な先読みですが、特定の数の出現に制限することに問題があります。私は文字と数字が発生する可能性がありますどこのすべての可能な組み合わせを含むことによってそれについて行くことができたとします

(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z]) ([A-Z][a-z][0-9]{6})|([A-Z][0-9][a-z][0-9]{5})| ... | ([0-9]{6}[a-z][A-Z]) 

しかし、それはそれを行うのは非常に回り道だし、よりよい解決策があります場合、私は思ったんだけど。

+0

あなたはどちらのエンジンを使用していますか?正規表現を複数のテストに分割することは可能ですか?すなわち、文字とは別に2文字の正確な文字が含まれていますか? –

+0

私はJava 8を使用しています。文字と数字はどこでもかまいません。ちょうど6桁、正確に1つの大文字、正確に1つの小文字が重要です。彼らがどこに位置しているかは問題ではありません。 – NoelAramis

+1

私はおそらく(正規表現なし)これをチェックするための短い方法を書いています。それははるかに理解し、維持することがより簡単になります。 – Henry

答えて

8

あなたは

^(?=[^A-Z]*[A-Z][^A-Z]*$)(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$ 

regex demo(ビットは複数行入力が原因で変更された)を参照してください使用することができます。 Javaでは、二重バックスラッシュを使用することを忘れないでください(数字を一致させるには\\dなど)。ここ

は故障である:

  • ^ - 文字列の先頭(なしマルチラインフラグがないと仮定すると、使用される)
  • (?=[^A-Z]*[A-Z][^A-Z]*$) - のみ1大文字が存在するかどうかを確認(任意のUnicodeと一致する\p{Lu}を使用します
  • (?=[^a-z]*[a-z][^a-z]*$) - 小文字が1つしかない場合は同様にチェックしてください(あるいは、\p{Ll}\P{Ll}をUnicode文字にマッチさせてください)
  • (?=(?:\D*\d){6}\D*$) - 文字列の先頭から6桁の数字を確認してください(=文字列の先頭から0桁以上の数字は使用できません。\Dは任意の文字に一致しますが、[^0-9]に置き換えることもできます) 、次に数字(\d)続いて、次に文字列の末尾($)まで0以上の数字以外の文字(\D*)が続く)、次いで
  • [a-zA-Z0-9]{8} - 丁度8英数字文字と一致。
  • $ - 文字列の最後。

ロジックに続いて、私たちも、ちょうど

^(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$ 

一つ我々は唯一[a-zA-Z0-9]と小文字と大文字と数字を許可するなどの条件を除去することができる、と私たちは2つの条件適用するときにこれを削減することができますの文字列(この場合は1文字は大文字である必要があります)と一致すると自動的に3番目の文字が実行されます。

のJava matches()方法でそれを使用して、開始とパターンの最後に^$アンカーを使用する必要はありませんが、あなたはまだ先読みして、それを必要とする:

String s = "K82v6686"; 
String rx = "(?=[^a-z]*[a-z][^a-z]*$)" +  // 1 lowercase letter check 
      "(?=(?:\\D*\\d){6}\\D*$)" +  // 6 digits check 
      "[a-zA-Z0-9]{8}";     // matching 8 alphanum chars exactly 
if (s.matches(rx)) { 
    System.out.println("Valid"); 
} 
+0

私は非常に短い変形にも薄くすることができます。 –

+0

6桁の(?=(?:\ D * \ d){6} \ D * $)チェックはどのようにして説明できますか?特に、非キャプチャグループ内の\ D *は何をしますか? – NoelAramis

+0

正規表現のその部分に説明を追加しました。実際には、すべてのルックアヘッド条件は逆の文字クラスに基づいています.SOMETHING以外の文字が0個以上一致した後、SOMETHINGの1回だけ指定した回数だけ一致します(制限数量子{{n、m} ')、SOMETHING以外の文字の出現数を文字列の最後まで一致させます。 –

1
Pattern.matches(".*[A-Z].*", s) && 
Pattern.matches(".*[a-z].*", s) && 
Pattern.matches(".*(\\D*\\d){6}.*", s) && 
Pattern.matches(".{8}", s) 

このタスクのためにオルタネートオートマトンを作成する必要があるので、文字の構成タイプにregexpsの連合を使用する方がはるかに簡単です。

少なくとも1つの小文字、1つの大文字、6桁が必要です.3つのクラスは互いに排他的です。そして最後の条件では、文字列の長さが正確にこれらの数値の合計であることが必要です。もちろん、我々はs.lenght() == 8を最後の条件語と言うかもしれませんが、これはスタイルを破るでしょう:)。

+0

説明を追加 – Tushar

0

文字列を字句順にソートし、次に^(?:[a-z][A-Z]|[A-Z][a-z])[0-9]{6}$と一致させます。

関連する問題