0

RegEx を使用した .NET プロジェクトで奇妙な問題が 1 つあります。以下の C# コードを参照してください。

const string PATTERN = @"^[a-zA-Z]([-\s\.a-zA-Z]*('(?!'))?[-\s\.a-zA-Z]*)*$";
const string VALUE = "Ingebrigtsen Myre (Øvre)";
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(PATTERN);
if (!regex.IsMatch(VALUE)) // <--- Infinite loop here
     return string.Empty;
// Some other code

このパターンを使用して、すべてのタイプの名前 (最初の名前、姓、ミドル ネームなど) を検証します。値はパラメーターですが、問題は頻繁に再現されないため、上記の定数として提供しました - *、(、) などの特殊記号のみを使用します (申し訳ありませんが、これらの記号の完全なリストはありません)。 .

この無限ループを修正するのを手伝ってくれませんか? 助けてくれてありがとう。

追加: このコードはプロジェクトの非常に基本的なレベルに配置されており、そこでリファクタリングを行いたくありません。この問題をすばやく修正したいだけです。

追加 2: 技術的にはループではないことは知っています。「regex.IsMatch(VALUE)」が終わらないことを意味していました。約 1 時間待ったが、まだ実行中であった。

4

3 に答える 3

3

自明でない正規表現:^[a-zA-Z]([-\s\.a-zA-Z]*('(?!'))?[-\s\.a-zA-Z]*)*$は、次のようにフリースペース モードでコメントを付けて記述する方が適切です。

Regex re_orig = new Regex(@"
    ^                 # Anchor to start of string.
    [a-zA-Z]          # First char must be letter.
    (                 # $1: Zero or more additional parts.
      [-\s\.a-zA-Z]*  # Zero or more valid name chars.
      (               # $2: optional quote.
        '             # Allow quote but only
        (?!')         # if not followed by quote.
      )?              # End $2: optional quote.
      [-\s\.a-zA-Z]*  # Zero or more valid name chars.
    )*                # End $1: Zero or more additional parts.
    $                 # Anchor to end of string.
    ",RegexOptions.IgnorePatternWhitespace);

英語では、この正規表現は基本的に次のように述べて[a-zA-Z]ます。

上記の正規表現では、次のような奇妙な名前が許可されていることに注意してください。"ABC---...'... -.-.XYZ "これは、必要なものである場合とそうでない場合があります。また、複数行の入力と、空白で終わる文字列も使用できます。

上記の正規表現の「無限ループ」の問題は、この正規表現が 2 つの単一引用符を続けて含む長い無効な入力に適用されると、壊滅的なバックトラッキングが発生することです。まったく同じ文字列に一致する (そして一致しない) 同等のパターンを次に示しますが、壊滅的なバックトラッキングは発生しません。

Regex re_fixed = new Regex(@"
    ^                # Anchor to start of string.
    [a-zA-Z]         # First char must be letter.
    [-\s.a-zA-Z]*    # Zero or more valid name chars.
    (?:              # Zero or more isolated single quotes.
      '              # Allow single quote but only
      (?!')          # if not followed by single quote.
      [-\s.a-zA-Z]*  # Zero or more valid name chars.
    )*               # Zero or more isolated single quotes.
    $                # Anchor to end of string.
    ",RegexOptions.IgnorePatternWhitespace);

そして、ここにあなたのコードコンテキストでの短い形式があります:

const string PATTERN = @"^[a-zA-Z][-\s.a-zA-Z]*(?:'(?!')[-\s.a-zA-Z]*)*$";
于 2013-08-09T16:03:52.147 に答える