dhardy
dhardy

Reputation: 1003

Regex replace between and including tags

I have the following line of text (META Title):

Buy [ProductName][Text] at a great price [/Text] from [ShopName] today.

I am replacing depending on what values I have.

I have it working as I require however I can't find the correct regex to replace:

[Text] at a great price [/Text]

The words (in a nd between square brackets) change so the only thing that will remain the same is:

[][/] 

i.e I may also want to replace

[TestText]some test text[/TestText] with nothing.

I have this working:

System.Text.RegularExpressions.Regex.Replace(SEOContent, @"\[Text].*?\[/Text]", @"");

I presumed the regex of:

[.*?].*?\[/.*?]

Would work but it didn't! - I'm coding in ASP.NET C# Thanks in advance,

Dave

Upvotes: 0

Views: 1336

Answers (1)

ΩmegaMan
ΩmegaMan

Reputation: 31721

Use a named capture to get the node name of [..], then find it again using \k<..>.

(\[(?<Tag>[^\]]+)\][^\[]+\[/\k<Tag>\])

Broken down using Ignore Pattern Whitespace and an example program.

string pattern = @"
(                # Begin our Match
  \[             # Look for the [ escape anchor
  (?<Tag>[^\]]+) # Place anything that is not antother ] into the named match Tag
  \]             # Anchor of ]
  [^\[]+         # Get all the text to the next anchor
  \[/            # Anchor of the closing [...] tag
  \k<Tag>        # Use the named capture subgroup Tag to balance it out
  \]             # Properly closed end tag/node.
)                # Match is done";

string text = "[TestText]some test text[/TestText] with nothing.";

Console.WriteLine (Regex.Replace(text, pattern, "Jabberwocky", RegexOptions.IgnorePatternWhitespace));
// Outputs
// Jabberwocky with nothing.

As an aside, I would actually create a tokenizing regex (using a regex If with the above pattern) and replace within matches by identify the sections by named captures. Then in the replace using a match evaluator replace the identified tokens such as:

string pattern = @"
(?(\[(?<Tag>[^\]]+)\][^\[]+\[/\k<Tag>\]) # If statement to  check []..[/] situation
  (                                      # Yes it is, match into named captures
   \[
   (?<Token>[^\]]+)                      # What is the text inside the [ ], into Token
   \]
   (?<TextOptional>[^\[]+)               # Optional text to reuse
   \[
   (?<Closing>/[^\]]+)                   # The closing tag info
   \]
  )
|                                        # Else, let is start a new check for either [] or plain text
 (?(\[)                                  # If a [ is found it is a token.
   (                                     # Yes process token
    \[
    (?<Token>[^\]]+)                     # What is the text inside the [ ], into Token
    \]
   )
  |                                      # Or (No of the second if) it is just plain text
  (?<Text>[^\[]+)                        # Put it into the text match capture.
 )
)
";


string text = @"Buy [ProductName] [Text]at a great price[/Text] from [ShopName] today.";

Console.WriteLine (
Regex.Replace(text,
              pattern,
              new MatchEvaluator((mtch) =>
              {

                 if (mtch.Groups["Text"].Success)           // If just text, return it.
                     return mtch.Groups["Text"].Value;

                 if (mtch.Groups["Closing"].Success)       // If a Closing match capture group reports success, then process
                 {
                    return string.Format("Reduced Beyond Comparison (Used to be {0})", mtch.Groups["TextOptional"].Value);
                 }

                  // Otherwise its just a plain old token, swap it out.
                  switch ( mtch.Groups["Token"].Value )
                  {
                     case "ProductName" : return "Jabberwocky"; break;
                     case "ShopName"    : return "StackOverFlowiZon"; break;
                  }


                  return "???"; // If we get to here...we have failed...need to determine why.

              }),
              RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture));
// Outputs:
// Buy Jabberwocky Reduced Beyond Comparison (Used to be at a great price) from StackOverFlowiZon today.

Upvotes: 1

Related Questions