SimonH
SimonH

Reputation: 1425

How to get a substring with Regex in C#

My program parses an XML-File which contains paths. Now I need to parse special folders like Appdata on different Windows devices:

<entry path="C:\Users\Simon\AppData\Roaming\myprogram" />

My attempt is to change the line into:

<entry path="#{APPDATA}\myprogram" />

and parse it using a Regular Expression:

string pattern = "#{ * }"; // what does fit here?

I've read some tutorials one Regex but I just can't figure out which Regex fits here.

How can I get the content between #{ and } using a regular Expression?

Upvotes: 0

Views: 121

Answers (4)

Cetin Basoz
Cetin Basoz

Reputation: 23867

Reading your question once again, maybe it is the other way you are asking?

void Main()
{
  string myXML = @"
  <x>
  <paths>
  <entry path=""#{APPDATA}\myprogram"" />
  <entry path=""#{APPDATA}\yourprogram"" />
  <entry path=""#{APPDATA}\hisprogram"" />
  <entry path=""C:\OtherFolder\DummyProgram"" />
  <entry src=""C:\OtherFolder\DummyProgram"" />
  </paths>
  <Other>Other</Other>
  </x>";

  var appdata = Environment.GetFolderPath( 
    Environment.SpecialFolder.ApplicationData );
XDocument doc = XDocument.Parse(myXML);

  doc.Descendants("entry")
  .Where(xd => xd.Attribute("path") != null &&
      ((string)xd.Attribute("path")).StartsWith("#{APPDATA}"))
  .ToList()
  .ForEach(e => {
     var oldPath = (string)e.Attribute("path");
     var newPath = Path.Combine(appdata, Path.GetFileName(oldPath));
     e.Attribute("path").SetValue(newPath);
     } );

  Console.WriteLine( doc.ToString() );

}

Upvotes: 1

poke
poke

Reputation: 388413

Just register general placeholders which you replace, e.g.

Dictionary<string, string> placeholders = new Dictionary<string, string>
{
    { "#{APPDATA}", @"C:\Users\Simon\AppData\Roaming" },
    { "#{SYSTEM32}", @"C:\Windows\System32" }
};

string ReplacePlaceholders (string text)
{
    foreach (var kv in placeholders)
    {
        text = text.Replace(kv.Key, kv.Value);
    }
    return text;
}

Used like this:

// this would come from the XML attribute
string path = @"#{APPDATA}\myprogram";

string newPath = ReplacePlaceholders(path);
Console.WriteLine(newPath); // C:\Users\Simon\AppData\Roaming\myprogram

As for actual values paths, you can also use Environment.GetFolderPath with the Environment.SpecialFolder enumeration to get the actual paths. But for the replacements and also other values, the answer still applies

Finally, since I wasn’t sure from your question in what direction you wanted to make these replacements, of course you can also reverse the mapping in above dictionary. I just assumed you had placeholders you wanted to replace by real paths.

Upvotes: 2

Cetin Basoz
Cetin Basoz

Reputation: 23867

Wouldn't it be simpler to use Linq To XML for this. I couldn't see an exact pattern in your question, but probably something like this:

void Main()
{
  string myXML = @"
  <x>
  <paths>
  <entry path=""C:\Users\Simon\AppData\Roaming\myprogram"" />
  <entry path=""C:\Users\Simon\AppData\Roaming\yourprogram"" />
  <entry path=""C:\Users\Simon\AppData\Roaming\hisprogram"" />
  <entry path=""C:\OtherFolder\DummyProgram"" />
  <entry src=""C:\OtherFolder\DummyProgram"" />
  </paths>
  <Other>Other</Other>
  </x>";

XDocument doc = XDocument.Parse(myXML);

  doc.Descendants("entry")
  .Where(xd => xd.Attribute("path") != null &&
      ((string)xd.Attribute("path")).ToLower().Contains("appdata"))
  .ToList()
  .ForEach(e => {
     var oldPath = (string)e.Attribute("path");
     var newPath = @"#{APPDATA}\" + Path.GetFileName(oldPath);
     e.Attribute("path").SetValue(newPath);
     } );

  Console.WriteLine( doc.ToString() );

}

Upvotes: 0

CodingWithSpike
CodingWithSpike

Reputation: 43768

You would want to use a match group in your regex. It would look like:

"#{(.*)}"

Then the Match.Groups property (documentation in the above link) would contain that "APPDATA" text.


This code prints "APPDATA" to the console

        var matches = Regex.Matches(@"#{APPDATA}\myprogram", "#{(.*)}");
        foreach (Match match in matches)
          Console.WriteLine(match.Groups[1].Value);

Upvotes: 1

Related Questions