tags:

views:

355

answers:

3

I've got the following string:

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")]

I need to alter it to look like the following:

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("myClass", "myVersion")]

The simplest way to achieve this, obviously, is to use a Regex to capture the pieces that I want from that string, and then concatenate the results with my extra text. However I'm looking to use the Regex.Replace() method to make the code a bit cleaner:

Regex generatedCodeAttributeRegex = new Regex("\\[[?:global::|]System.CodeDom.Compiler.GeneratedCodeAttribute\\((\"System.Data.Design.TypedDataSetGenerator\",[\\s+]\"2.0.0.0\")\\)\\]");

inputFileContent = generatedCodeAttributeRegex.Replace(inputFileContent, delegate(Match m)
{
  return string.Format("\"{0}\", \"{1}\"",
                       this.GetType(),
                       Assembly.GetExecutingAssembly().GetName().Version);
});

From my understanding, this should replace the captured group with the text specified in the delegate... the problem is that it doesn't. What am I doing wrong? And is it possible to achieve this with the Regex.Replace(string, string) overload?

A: 

Your regex does not match because you wrote [?:global::|], which is a character range containing the characters ?, :, g, l, o, b, a, :, and |. You probably meant (?:global::|) which is the same as (?:global::)?, i.e. "global:: or nothing".

Also note that by not escaping the dots, they will match anything - not just literal dots. Though that is unlikely to cause problems.

If you fix that, it will work, but not quite as you want, since Regex.Replace replaces the whole match, not just the part in the capturing group.

sepp2k
That's closest to the answer I was looking for, and thanks for picking up the "global::" mistake. That's not the first time I've confused ( and [ and I'm sure it won't be the last...
Ian Kemp
You made the same mistake with `[\\s+]` -- in that case you should just remove the brackets.
Alan Moore
A: 

Not sure about C# specialties, but I'd guess that the regular expression is plain wrong. The square brackets are used in a wrong way. They can only define character classes and cannot be used for capturing of subpatterns. All this assuming C# uses regular perl-style regexps.

The correct regular expression for this would be (attention, not escaped):

\[(global::)?System\.CodeDom\.Compiler\.GeneratedCodeAttribute\("([^"]+)", "([^"]+)"\)\]

My advice: go to http://regexpal.com/ to test your regular expressions first, then implement them in your code. Saves a lot of trouble.

Steffen Müller
I prefer Expresso (http://www.ultrapico.com/Expresso.htm) - available offline, C#-specific and generates regex code that you can paste straight into your app.
Ian Kemp
+1  A: 

The way i would do this is with a look behind @"(?<=)" and look ahead @"(?=)" like so:

"(?<=\[global::System\.CodeDom\.Compiler\.GeneratedCodeAttribute\()([^\)]*)(?=\)\])"

Then your replacement string should work as is.

Rich Oliver
That didn't work for me.
Ian Kemp
Sorry, should have been a a literal:@"(?<=\[global::System\.CodeDom\.Compiler\.GeneratedCodeAttribute\()([^\)]*)(?=\)\])"
Rich Oliver