Reputation: 80
In the following piece of code (C#), I would like to replace the value of the Order and GUID in the ContentType annotation:
[ContentType(
DisplayName = "My First Block",
Order = 133536,
GUID = "0f02e38a-a6e2-4333-9bd1-c61cf573d8d3",
Description = "Just an example block.",
GroupName = "Blocks.Content"
)]
public class MyFirstBlock : BaseBlock
{
[CultureSpecific]
[Display(
Name = "Title",
Order = 100,
Description = "The title",
GroupName = "Information")]
[Required]
public virtual XhtmlString Title { get; set; }
}
I'm using the following regular expressions to find the values:
Order: (?<=Order = )\d{4,}(?=[,)])
GUID: (?<=GUID = \").*(?=\")
And these work but they have some shortcomings. For the Order regex, I would like to not have to look for a minimum of 4 digits. I'd much rather do (?<=Order = )\d*(?=[,)])
so it will also find the right location if the current order value is less than 4 digits or even not entered at all. But this will also match the order in the Display annotation for the Title. I've tried making the expression not greedy, as is the accepted answer in just about every search result I find when googling my question, but that doesn't seem to do anything.
For the GUID, I'm running into the same problem. I can't be sure that there will not be another GUID somewhere in the document, that I don't want to replace. So for this expression the problem is basically the same, I only want to find the value of the first GUID in the document.
Another approach I've tried is to look for the Order and GUID inside the ContentType block, but I've not been able to get that to work.
A little background information to put this question in context: I'm writing a VS Extension that will generate the order number based on the text selected by the user and also replace the GUID with a newly generated GUID. I'm using EnvDTE.TextDocument.ReplacePattern() to replace the value for the order and GUID after they've been generated.
Upvotes: 1
Views: 90
Reputation: 626845
You may use the following solution:
var result = Regex.Replace(
Regex.Replace(input, @"(?s)(\[ContentType\((?:(?!\)]).)*?\bOrder\s*=\s*)\d*(.*?\)])", "${1}<<ORDER>>$2"),
@"(?s)(\[ContentType\((?:(?!\)]).)*?\bGUID\s*=\s*""?)[\w-]*(.*?\)])",
"${1}<<GUID>>$2");
See the C# online demo that shows that the Order
and GUID
values are only replaced in the ContentType
part:
Order = <<ORDER>>,
GUID = "<<GUID>>",
Note that the replacement backreferences are made unambiguous by using curly braces since most probably your replacements will be starting with digits and that could create an invalid group reference.
The pattern matches:
(?s)
- enables .
to match newlines(\[ContentType\((?:(?!\)]).)*?\bGUID\s*=\s*"?)
- Group 1 capturing:
\[ContentType\(
- a [ContentType(
substring(?:(?!\)]).)*?
- any char not starting a )]
sequence, as few as possible, \bGUID
- a whole word GUID
(or Order
)\s*=\s*
- a =
enclosed with 0+ whitespaces"?
- an optional "
[\w-]*
- 0 or more word or -
chars(.*?\)])
- Group 2: any chars as few as possible up to the first )]
including them.Upvotes: 1