1

次のシナリオを考えると、私がまだよく知らない正規表現を使用してより良い解決策を書くことができるかどうか疑問に思っています。私の基本的な C# 文字列操作は多少機能しますが、穴が開いています。あなたの考えやアイデアは大歓迎です。

どうもありがとう、

クレイグ

以下の文字列 "story" を指定して、次のことを行うスクリプトを作成します。

  1. 可変テキストは で囲まれてい{ }ます。
  2. 変数のテキストが空白の場合は、 で囲まれた他のテキストをすべて削除します[ ]
  3. 削除するテキストは、 で深くネストできます[ ]

フォーマット:

    XYZ Company [- Phone: [({404}) ]{321-4321} [Ext: {6789}]]

例:

  1. すべての可変テキストが入力されました。

    XYZ Company - Phone: (404) 321-4321 Ext: 6789
    
  2. 拡張子が入力されていません。「Ext:」を削除してください。

    XYZ Company - Phone: (404) 321-4321
    
  3. 内線番号と市外局番が入力されていない場合は、「Ext:」と「( )」を削除してください。

    XYZ Company - Phone: 321-4321
    
  4. 内線番号なし、電話番号なし、市外局番なしの場合は、「Ext:」と「( )」と「- Phone:」を削除します。

    XYZ Company
    

これがプレーンな文字列操作による私の解決策です。

private string StoryManipulation(string theStory)
    {
        // Loop through story while there are still curly brackets
        while (theStory.IndexOf("{") > 0)
        {
            // Extract the first curly text area
            string lcCurlyText = StringUtils.ExtractString(theStory, "{", "}");                

            // Look for surrounding brackets and blank all text between
            if (String.IsNullOrWhiteSpace(lcCurlyText))
            {
                for (int lnCounter = theStory.IndexOf("{"); lnCounter >= 0; lnCounter--)
                {
                    if (theStory.Substring(lnCounter - 1, 1) == "[")
                    {
                        string lcSquareText = StringUtils.ExtractString(theStory.Substring(lnCounter - 1), "[", "]");
                        theStory = StringUtils.ReplaceString(theStory, ("[" + lcSquareText + "]"), "", false);
                        break;
                    }
                }
            }
            else
            {
                // Replace current curly brackets surrounding the text
                theStory = StringUtils.ReplaceString(theStory, ("{" + lcCurlyText + "}"), lcCurlyText, false);
            }
        }
        // Replace all brackets with blank (-1 all instances)
        theStory = StringUtils.ReplaceStringInstance(theStory, "[", "", -1, false);
        theStory = StringUtils.ReplaceStringInstance(theStory, "]", "", -1, false);
        return theStory.Trim();
    }
4

1 に答える 1

2

ネストされた構造を扱うことは、通常、正規表現の範囲を超えています。しかし、ループ内で正規表現の置換を実行すると、裏返しに解決策があると思います。ただし、コールバック関数が必要になります (a MatchEvaluator):

string ReplaceCallback(Match match)
{
    if(String.IsNullOrWhiteSpace(match.Groups[2])
        return "";
    else
        return match.Groups[1]+match.Groups[2]+match.Groups[3];
}

次に、エバリュエーターを作成できます。

MatchEvaluator evaluator = new MatchEvaluator(ReplaceCallback);

そして、置換によって何も変更されなくなるまで、これをループで呼び出すことができます。

newString = Regex.Replace(
    oldString,
    @"
    \[    # a literal [
    (     # start a capturing group. this is what we access with "match.Groups[1]"
        [^{}[\]]
          # a negated character class, that matches anything except {, }, [ and ]
        * # arbitrarily many of those
    )     # end of the capturing group
    \{    # a literal {
    ([^{}[\]]*)
          # the same thing as before, we will access this with "match.Groups[2]"
    }     # a literal }
    ([^{}[\]]*)
          # "match.Groups[3]"
    ]     # a literal ]
    ",
    evaluator,
    RegexOptions.IgnorePatternWhitespace
);

正規表現の空白のないバージョンは次のとおりです。

\[([^{}[\]]*)\{([^{}[\]]*)}([^{}[\]]*)]
于 2012-11-07T22:49:23.997 に答える