Reputation: 1003
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
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