2011-11-29 13 views
6

入力文字列を検証する正規表現を書いています。最小長は8文字(英数字と句読記号で構成されています)でなければなりません。また、少なくとも1桁と1文字の英字が必要です。だから私は、正規表現を作ってみた:regexのlookaheadを置き換えるには?

^(?=.*[0-9])(?=.*[a-zA-Z])[a-zA-Z0-9-,._;:]{8,}$ 

は、今私はどのように私は正規表現を書き換える必要があり、先読みをサポートしていない言語でこの正規表現を書き換える必要がありますか?

1foo,bar 
foo,bar1 
1fooobar 
foooobar1 
fooo11bar 
1234x567 
a1234567 

無効な入力:

有効な入力がある

fooo,bar 
1234-567 
.1234567 
+2

は、異なる機能のサポートが変化するため、役立つかもしれません。 – fncomp

+0

@Josh:質問には「perl」というタグが付きます。 –

+1

@mu先読みをサポートしていないPerlの実装がありますか? – fncomp

答えて

7

2つのアプローチがあります。一つは、すべての可能な代替案を処理する単一の式を構成することです:

^[a-zA-Z][0-9][a-zA-Z0-9-,._;:]{6,}$ 
    | 
^[a-zA-Z][a-zA-Z0-9-,._;:][0-9][a-zA-Z0-9-,._;:]{5,}$ 
    | 
^[a-zA-Z][a-zA-Z0-9-,._;:]{2}[0-9][a-zA-Z0-9-,._;:]{4,}$ 

などこれはcombinatoric悪夢ですが、それは働くだろう。

^[a-zA-Z0-9-,._;:]{8,}$   # check length and permitted characters 

[a-zA-Z].*[0-9]|[0-9].*[a-zA-Z] # check required characters 

EDIT:

Aはるかに単純なアプローチは二度2つの式を使用して、同じ文字列を検証することです@briandfoyが正しくポイントそれがより効率的になることを別途必要な各文字を検索する:

[a-zA-Z]       # check for required alpha 

[0-9]       # check for required digit 
+0

あなたの2番目の正規表現は、多くの繰り返し作業です。 2つの別々の正規表現を使ってアルファと数字をチェックする:qr/[az]/iとqr/[0-9 –

+0

@MetaEd私は単一行の正規表現を探していたが、 lokkaheadのような機能私はあなたの第2の解決策に行くでしょう。ありがとうございます – alexyz78

0

私は今を考え出すことができる最高の

(.*[a-zA-Z].*[0-9].*|.*[0-9].*[a-zA-Z].*) 

あるしかし、あなたはの長さをチェックする必要が文字列を別々に

2

この質問はperlとしてタグ付けされた元だった、そしてそれは私がそれに答え方法です。オラクルのものについては、あなたが同じことをどうやってやるか分かりません。しかし、私はそれがそれまでに得られる前に、このことを検証しようとしていました。

これは1つの正規表現では行いません。ルールを変更する場合、新しい正規表現を作成する作業は同じ量になります。私はバックトラックをすべて許したくないので、たとえそれが利用可能であっても、このための探索法を使用しません。

これは多くのコードのようですが、問題を解決する部分は単なるサブルーチンです。それは非常に単純なパターンを持っています。パスワードルールが変更されると、パターンが追加または削除されます。studyを使用する価値があるかもしれませんが、私はそれを調査していない:

use v5.10; 
use strict; 

use Test::More; 

my @valids = qw(
    1foo,bar 
    foo,bar1 
    1fooobar 
    foooobar1 
    fooo11bar 
    ); 

my @invalids = qw( 
    fooo,bar 
    short 
    nodigitbutlong 
    12345678 
    ,,,,,,,, 
    ); 

sub is_good_password { 
    my($password) = @_; 

    state $rules = [ 
     qr/\A[A-Z0-9,._;:-]{8,}\z/i, 
     qr/[0-9]/, 
     qr/[A-Z]/i, 
     ]; 

    foreach my $rule (@$rules) { 
     return 0 unless $password =~ $rule; 
     } 

    return 1; 
    }  

foreach my $valid (@valids) { 
    ok(is_good_password($valid), "Password $valid is valid"); 
    } 

foreach my $invalid (@invalids) { 
    ok(! is_good_password($invalid), "Password $invalid is invalid"); 
    } 

done_testing(); 
+0

私はPerlからOracleに移植しなければならないので、私は 'Perl'とタグ付けしました。先読みをサポートしていない複数の言語があり、実装言語よりも正規表現そのものに興味があるため、私は '目的地'の言語を指定しませんでした。 – alexyz78

0

私は最高のパフォーマンスを得るために、これらのアイデアで遊んでます:

  • は短い有効なため高速化する必要があります入力が、「0a000000000000000000」または「aaaaaaaaaaaaaaa」などの入力のために(バックトラック)遅くなります:無効なのが多い場合

    regexp_like(regexp_substr(input_string, '^[a-zA-Z0-9_,.;:-]{8,}$'), 
          '[0-9].*[a-zA-Z]|[a-zA-Z].*[0-9]') 
    
  • は速くする必要があります入力(2行目に[^ ...]逃してはいけない):言語を記述

    (length(input_string) >= 8 and 
    not regexp_like(input_string, '[^a-zA-Z0-9_,.;:-]') and 
    regexp_like(input_string, '[a-zA-Z]') and 
    regexp_like(input_string, '[0-9]')) 
    
関連する問題