2014-11-18 23 views
6

Şifre stratejisinde 4 gereksinim vardır. Aşağıdakilerden herhangi birini aşağıdakiDört normal gereksinimden en az üçünü eşleştirmenin en iyi yolu

  1. küçük harf içermelidir.
  2. büyük harf.
  3. sayısal.
  4. özel karakter. '|'

aşağıdaki regex Ben kullanabilirsiniz bildiğim vakası,

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{4,8}$ 

maç olacak Ancak, tüm kombinasyonları ilan etmek için, akşam yemeği uzun bir normal ifade üretecektir. '|' Ile değiştirmenin en iyi yolu nedir? Böylece, girdinin kombinasyondaki üç koşuldan herhangi birini içerip içermediğini kontrol edebilir mi?

+0

Şunu Bu '^ (= * [_ (= * \ D?.) (= * [A-Za-z]?.?).? \ W]). {4,8} ' –

+0

Neden sadece okunabilirlik için basit tutmak ve 4 farklı regex kullanmak? – Wolph

+0

benim için net değil. Bazı geçerli ve geçersiz eşleşmeler sağlayabilir misiniz? –

cevap

3

tek ihtiyaçlarınızı karşılayacak olabilecek aşağıdaki bir PCRE lezzet kullanıyorsanız (okunabilirlik için biçimlendirilmiş) :

^(?: 
    ((?=.*\d))((?=.*[a-z]))((?=.*[A-Z]))((?=.*[^a-zA-Z0-9]))| 
    (?1)  (?2)   (?3)        | 
    (?1)  (?2)      (?4)    | 
    (?1)     (?3)   (?4)    | 
       (?2)   (?3)   (?4) 
).{4,8}$ 

Regular expression visualization

Tek kaplı:

^(?:((?=.*\d))((?=.*[a-z]))((?=.*[A-Z]))((?=.*[^a-zA-Z0-9]))|(?1)(?2)(?3)|(?1)(?2)(?4)|(?1)(?3)(?4)|(?2)(?3)(?4)).{4,8}$ 

Demo JavaScript regex lezzet özyinelemeye desteklemediği


Debuggex üzerine (aslında birçok şeyi desteklemez). Daha örneğin kullanım yerine 4 farklı regexes:

var validate = function(input) { 
    var regexes = [ 
     "[A-Z]", 
     "[a-z]", 
     "[0-9]", 
     "[^a-zA-Z0-9]" 
    ];  
    var count = 0; 
    for (var i = 0, n = regexes.length; i < n; i++) { 
     if (input.match(regexes[i])) { 
      count++; 
     } 
    }  
    return count >=3 && input.match("^.{4,8}$");  
}; 
+0

Özyineleme yapmaz eşleşmesi daha uzun sürer? Bu "en iyi yol" nasıl? Ayrıca, ilk satır bir '(? DEFINE' bloğu içinde olmak için bir aday gibi görünüyor. – Unihedron

+0

@Unihedron Tek bir regex ile, korkarım ki daha iyi bir yol yoktur. En iyi yol, 4 farklı regex kullanmaktır: çok daha okunabilir ve daha az verimli olması gerekmez. '(?: ...)' yakalama dışı bir gruptur. – sp00m

+0

@ sp00m Teşekkürler, ancak javascript kullanıyorum. Ve mantığın orijinali kullanmakla aynı olduğunu, ancak grup numarasıyla değiştirmeyi düşünüyorum. – panda

1

Elbette, aynı regex'in küçük bir modifikasyonunu kullanan, ancak kısa bir kod yazma gereksinimi olan bir yöntem.

^(?=(\D*\d)|)(?=([^a-z]*[a-z])|)(?=([^A-Z]*[A-Z])|)(?=([a-zA-Z0-9]*[^a-zA-Z0-9])|).{4,8}$ 

Burada beş yakalama grubunuz var - Bunlardan en az 3 tanesinin boş olup olmadığını kontrol edin. Yakalama için boş bir grup etkili bir şekilde, lookahead içindeki alternatifin eşleştiğini ve sol taraftaki yakalama grubunun eşleştirilemediğini gösterir.

preg_match("/^(?=(\\D*\\d)|)(?=([^a-z]*[a-z])|)(?=([^A-Z]*[A-Z])|)(?=([a-zA-Z0-9]*[^a-zA-Z0-9])|).{4,8}$/", $str, $matches); 

$count = -1; // Because the zero-eth element is never null. 
foreach ($matches as $element) { 
    if (!empty($element)) { 
     $count += 1; 
    } 
} 

if ($count >= 3) { 
    // ... 
} 

Veya Java: PHP Örneğin

,

Matcher matcher = Pattern.compile(...).matcher(string); 

int count = 0; 

if (matcher.matches()) 
    for (int i = 1; i < 5; i++) 
     if (null != matcher.group(i)) 
      count++; 

if (count >= 3) 
    // ...