2

次の 3 つの可能性すべてを可能にする単一の正規表現を作成する必要があります(問題がある場合は .NET 3.5 Regex を使用)。

  1. [A-Z]{2,3}
  2. [A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}
  3. [A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}-[A-Z0-9]{2,3}

したがってBIG、、、BIG-A9またはは一致しますBIG-A09-SDBIG-F、、、またはは一致しません。BIG-A9S-BIG-A09-S

私はいくつかのことを明確にする必要があります:

  • ラインの一部だけでなく、ライン全体を一致させる必要があります。

  • この文字列を に入力しているユーザーにフィードバックを提供しようとしていますTextBox。したがって、TextBox のコンテンツが変更されるたびにテストするために使用できる正規表現を探しています。たとえば、ユーザーが「A」と入力すると、ケース 1 にまだ一致していないため、フィードバックは否定的になります。「AA」と入力すると、ケース 1 に一致したため、フィードバックは肯定的になります。「AAE」と入力した後、ケース 1 に一致したため、引き続き肯定的なフィードバックを受け取る必要があります。「AA7」と入力すると、フィードバックは否定的になるはずです。その後、入力を続けて「AAE-」と入力すると、ケース 2 をまだ満たしておらず、ケース 1 を超えているため、フィードバックは再び否定的になります。

私は髪を引っ張っています(少し残っています)。

うまくいく方法でこれを表現する方法を知っている人はいますか?

4

3 に答える 3

5

正規表現パターンは、他のプレフィックスであるというプロパティに従って順序付けできます。ネストされたオプションのサフィックスを試してください:

(?:[A-Z]{2,3}(?:-[A-Z][A-Z0-9]{1,2}(?:-[A-Z0-9]{2,3})?)?)
于 2013-08-16T16:55:46.960 に答える
3

原則として、正規表現は左端の最も長い ruleに従って一致し、その正式な表現 (Posix 標準から) は次のとおりです。

検索は、文字列の可能なすべてのサフィックスがパターンに一致するプレフィックスについてテストされたかのように実行されます。一致するプレフィックスを含む最長のサフィックスが選択され、選択されたサフィックスの可能な最長の一致するプレフィックスが一致するシーケンスとして識別されます。

あなたの 3 つの可能性はそれぞれ、前の可能性の拡張です。3番目で最も長いものから始めます:

[A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}-[A-Z0-9]{2,3}

これには 3 つのコンポーネントがあり、それぞれが独自の正規表現です。

  • [A-Z]{2,3}
  • -[A-Z][A-Z0-9]{1,2}
  • -[A-Z0-9]{2,3}

まず、それぞれをグループ化する必要があります。

  • ([A-Z]{2,3})
  • (-[A-Z][A-Z0-9]{1,2})
  • (-[A-Z0-9]{2,3})

次に、最後の 2 つを組み合わせて、より長い正規表現にすることができます。

  • ([A-Z]{2,3})
  • (-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})

2 番目のセグメントがある場合、3 番目のセグメントはオプションであることに注意してください。そうするために:

  • ([A-Z]{2,3})
  • (-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?

次に、2 番目のコンポーネント全体をグループ化して、それが不可欠な部分であることを示します。

  • ([A-Z]{2,3})
  • ((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)

最初のコンポーネントがある場合、その 2 番目のコンポーネント全体がオプションであるため、接尾辞演算子を使用してオプションであること?を示します。

  • ([A-Z]{2,3})
  • ((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?

最後に、2 つの正規表現を連結して最終的な表現を作成します。

([A-Z]{2,3})((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?

ほらね。正規表現エンジンでは、後戻りがなく、最小限の先読みが必要です。

以下のOPのコメントから、目的の一致は文字列全体であるように見えます。そう...

デフォルトでは、正規表現はソース文字列の左端で最も長い一致を見つけます。文字列全体または全体と一致させたい場合は、式をメタパターンで固定する必要があります^。これにより、一致がその位置で行頭に$固定され、一致がその位置で行末に固定されます。 . そう...

  • ^abc、プレフィックスに一致し、abc( abcabcabcabccaabcdefgなど) で始まる任意の文字列に一致します。、 などxyzabcには一致しません。ab

  • abc$、同様に、サフィックスに一致し、abc( abcxyzabcなど) で終わる任意の行に一致します。、、 などabには一致しません。xyzababcxyz

  • ^abc$文字列のみに一致し、他には何も一致しabcません。

行全体に一致させるには、上記の正規表現を使用してアンカーをドロップします。

^([A-Z]{2,3})((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?$

それだけです。ただし、 、 、 の動作は.、または 正規表現がorオプションでコンパイルされ^$いるかどうかに依存することに注意してください。は、文字列全体の先頭と末尾のみに一致し、 以外の任意の文字に一致することを意味します。は、文字列内の任意の行の先頭と末尾に一致し、 を含む任意の文字に一致することを意味します。MultilineSingleLineSingleLine^$.\nMultiLine^$. \n

一致したさまざまなコンポーネントを見つけたい場合は、正規表現にマークアップを追加して、名前付きグループを作成できます。

(?<prefix>[A-Z]{2,3})((-(?<middle>[A-Z][A-Z0-9]{1,2}))(-(?<suffix>[A-Z0-9]{2,3}))?)?

これにより、一致したグループに名前でアクセスできるようになり、コードが読みやすくなります。

Regex rx = new Regex( @"(?<prefix>[A-Z]{2,3})((-(?<middle>[A-Z][A-Z0-9]{1,2}))(-(?<suffix>[A-Z0-9]{2,3}))?)?" , RegexOptions.ExplicitCapture );
Match m = rx.Match(s) ;

if ( m.Success )
{
  string prefix = m.Groups["prefix"].Value ;
  string middle = m.Groups["middle"].Value ;
  string suffix = m.Groups["suffix"].Value ;

  Console.WriteLine( "prefix: {0}" , prefix ) ;
  Console.WriteLine( "middle: {0}" , middle ) ;
  Console.WriteLine( "suffix: {0}", suffix  ) ;

}

パフォーマンスのヒント:名前付きグループを使用して正規表現をコンパイルするとRegexOptions.ExplicitCapture、特に正規表現が複雑になる場合に大きな助けになります。

正規表現に慣れていない場合 (そうでない場合でも!)、Jeffrey Friedlの最も優れた作品であるMastering Regular Expressionsを読む必要があります。

正規表現をマスターする

于 2013-08-16T18:16:21.313 に答える
0

私に関する限り、Nicholas Carey が答えを提供してくれました。ほとんどの回答については、彼の回答を参照してください。本はすでに注文済みです!

ユーザーが入力を入力するときに継続的にフィードバックを提供するという要件を満たすために、Windows フォームの TextChanged イベント ハンドラーとして次のコードを登録しました。

    private void TheTextChanged(object sender, EventArgs e)
    {
        var rx = new Regex(@"(?<prefix>[A-Z]{2,3})((-(?<middle>[A-Z][A-Z0-9]{1,2}))(-(?<suffix>[A-Z0-9]{2,3}))?)?", RegexOptions.ExplicitCapture);
        Match m = rx.Match(textbox.Text);

        if (m.Success)
        {
            string prefix = m.Groups["prefix"].Value;
            string middle = m.Groups["middle"].Value;
            string suffix = m.Groups["suffix"].Value;
            if (prefix != "")
            {
                textbox.BackColor = prefix.Equals(textbox.Text) ? Color.LightGreen : Color.LightPink;
                if (middle != "")
                {
                    string twoparts = prefix + "-" + middle;
                    textbox.BackColor = twoparts.Equals(textbox.Text) ? Color.LightGreen : Color.LightPink;
                    if (suffix != "")
                    {
                        string threeparts = prefix + "-" + middle + "-" + suffix;
                        textbox.BackColor = threeparts.Equals(textbox.Text) ? Color.LightGreen : Color.LightPink;
                    }
                }
            }
        }
        else
        {
            textbox.BackColor = Color.LightPink;
        }
    }

ここにWPFバージョンがあります。

    private void TheTextChanged(object sender, TextChangedEventArgs e)
    {
        var rx = new Regex(@"(?<prefix>[A-Z]{2,3})((-(?<middle>[A-Z][A-Z0-9]{1,2}))(-(?<suffix>[A-Z0-9]{2,3}))?)?", RegexOptions.ExplicitCapture);
        Match m = rx.Match(textbox.Text);

        if (m.Success)
        {
            string prefix = m.Groups["prefix"].Value;
            string middle = m.Groups["middle"].Value;
            string suffix = m.Groups["suffix"].Value;
            if (prefix != "")
            {
                textbox.Background = prefix.Equals(textbox.Text) ? Brushes.LightGreen : Brushes.LightPink;
                if (middle != "")
                {
                    string twoparts = prefix + "-" + middle;
                    textbox.Background = twoparts.Equals(textbox.Text) ? Brushes.LightGreen : Brushes.LightPink;
                    if (suffix != "")
                    {
                        string threeparts = prefix + "-" + middle + "-" + suffix;
                        textbox.Background = threeparts.Equals(textbox.Text) ? Brushes.LightGreen : Brushes.LightPink;
                    }
                }
            }
        }
        else
        {
            textbox.Background = Brushes.LightPink;
        }
    }

すばらしい回答をありがとうございました!! 次回はもっとはっきり言ってみます。

于 2013-08-17T03:04:15.073 に答える