特定の正規表現に一致するランダムな英数字の文字列を作成するにはどうすればよいでしょうか?
これは、通常のパスワード要件を満たす初期パスワードを作成するためのものです。
特定の正規表現に一致するランダムな英数字の文字列を作成するにはどうすればよいでしょうか?
これは、通常のパスワード要件を満たす初期パスワードを作成するためのものです。
String :: Random in Perlは、正規表現のサブセットからランダムな文字列を生成します。
#!/usr/bin/perl
use strict;
use warnings;
use String::Random qw/random_regex/;
print random_regex('[A-Za-z]{3}[0-9][A-Z]{2}[!@#$%^&*]'), "\n";
うーん、ただ考えているだけですが、正規表現に一致するランダム入力を生成するという一般的な質問は、ランダムの十分に緩和された定義と正規表現の十分に厳密な定義のために実行可能に思えます。()|* とアルファベット文字のみを許可する古典的な正式な定義を考えています。
正規表現は、有限オートマトンと呼ばれるフォーマル マシンにマッピングできます。このようなマシンは、最終状態と呼ばれる特定のノード、初期状態と呼ばれるノード、および各エッジのアルファベットからの文字を持つ有向グラフです。初期状態から開始し、グラフの各文字でラベル付けされた 1 つのエッジをトラバースし、最終状態で終了できる場合、単語は正規表現によって受け入れられます。
グラフを作成し、最終状態から開始してランダムなエッジを逆方向にたどり、パスを追跡することができます。標準的な構成では、グラフ内のすべてのノードは初期状態から到達可能であるため、取り返しのつかない間違いを犯したり、バックトラックする必要があることを心配する必要はありません。初期状態に到達したら、停止してパスを読み取ります。それが正規表現の一致です。
ただし、いつ、または初期状態に到達するかどうかについて、特に保証はありません。生成された文字列がどのような意味で「ランダム」であるか、またどのような意味で最初に言語からのランダムな要素を望んでいるのかを理解する必要があります。
しかし、それは問題について考えるための出発点かもしれません!
これを書き終えたので、単純な文字列が残るまで、選択肢を繰り返し解決して正規表現パターンを単純化する方が簡単なように思えます。パターン内のアルファベット以外の最初の文字を見つけます。* の場合は、前の項目を何回か繰り返して、* を削除します。| の場合は、OR されたアイテムのどれを保持し、残りを削除するかを選択します。左括弧についても同じことを行いますが、一致する右括弧に続く文字を調べます。これは、最初に正規表現をツリー表現に解析して、括弧のグループ化構造を扱いやすくすると、おそらく簡単です。
正規表現が実際に何かに一致するかどうかを判断することは停止問題と同等であると心配している人へ: いいえ、通常の言語は非常にうまく動作します。2 つの正規表現が、受け入れられる文字列の同じセットを記述しているかどうかがわかります。基本的に上記のマシンを作成し、アルゴリズムに従って標準的な最小限の同等のマシンを生成します。2 つの正規表現に対してこれを行い、結果の最小マシンが同等かどうかを確認します。これは簡単です。
特定の問題がある場合は、特定の正規表現を念頭に置いている可能性があります。私はその正規表現を使って、それが何を意味するのかを単純な人間の用語で理解し、そこから作業を進めます。
一般的な正規表現ランダム マッチ ジェネレーターを作成することは可能だと思いますが、特定のケースを処理するよりもはるかに多くの作業が必要になる可能性があります。そのケースが年に数回変更されたとしてもです。
(実際には、最も一般的な意味でランダムな一致を生成することはできないかもしれません.「どの文字列もこの正規表現に一致するか」という問題は、隠れた問題であるという漠然とした記憶があります.非常に削減された正規表現言語ではあなたにはもっと運があるかもしれません。)
Lexer と Generator で構成されるParsleyを作成しました。
$generator = new \Gajus\Parsley\Generator();
/**
* Generate a set of random codes based on Parsley pattern.
* Codes are guaranteed to be unique within the set.
*
* @param string $pattern Parsley pattern.
* @param int $amount Number of codes to generate.
* @param int $safeguard Number of additional codes generated in case there are duplicates that need to be replaced.
* @return array
*/
$codes = $generator->generateFromPattern('FOO[A-Z]{10}[0-9]{2}', 100);
上記の例は、それぞれ「FOO」で始まる 100 個のコードを含む配列を生成し、その後に「ABCDEFGHKMNOPRSTUVWXYZ23456789」干し草スタックからの 10 文字と「0123456789」干し草スタックからの 2 つの数字が続きます。
正規表現を解析し、ランダムな長さなどの文字範囲のランダムなメンバーを生成できる文字列ジェネレーターを作成する必要があります。
はるかに簡単なのは、特定のルール (小文字で始まり、少なくとも 1 つの句読点、大文字と数字、少なくとも 6 文字など) を使用してランダムなパスワード ジェネレータを作成し、正規表現を作成して、作成されたパスワードが上記の規則は有効です。
可能です (たとえば、Haskell 正規表現モジュールには、特定の正規表現に一致するはずの文字列を自動的に生成するテスト スイートがあります)。
ただし、手元にある単純なタスクの場合は、単純なパスワード ジェネレーターを使用して、その出力を正規表現でフィルター処理する方がよい場合があります。
最小の長さと 3-of-4* (または同様の) 要件の両方があると仮定すると、適切なパスワード ジェネレーターを使用する傾向があります。
過去にいくつか (Web ベースとコマンドラインの両方で) 作成しましたが、3-of-4 ルールに合格するために生成された文字列を複数スキップする必要はありませんでした。