如何在c#中使用正则表达式获得子字符串

本文关键字:正则表达式 字符串 | 更新日期: 2023-09-27 18:16:12

程序解析一个包含路径的xml文件。现在我需要解析不同Windows设备上的特殊文件夹,如Appdata:

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

我试着把这行改成:

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

并使用正则表达式解析它:

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

我读过一些关于正则表达式的教程,但我就是不知道哪个正则表达式适合这里。

如何使用正则表达式获得#{}之间的内容?

如何在c#中使用正则表达式获得子字符串

只需注册一般占位符,例如

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;
}

像这样使用:

// this would come from the XML attribute
string path = @"#{APPDATA}'myprogram";
string newPath = ReplacePlaceholders(path);
Console.WriteLine(newPath); // C:'Users'Simon'AppData'Roaming'myprogram

对于实际值路径,您也可以使用Environment.GetFolderPathEnvironment.SpecialFolder枚举来获得实际路径。但是对于替换和其他值,答案仍然适用

最后,因为我不确定从你的问题中你想要在哪个方向进行这些替换,当然你也可以在上面的字典中反向映射。我只是假设您有想用实际路径替换的占位符。

您可能希望在正则表达式中使用匹配组。它看起来像:

"#{(.*)}"

然后是Match。Groups属性(上面链接中的文档)将包含"APPDATA"文本。


这段代码将"APPDATA"打印到控制台

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

再次阅读你的问题,也许这是你问的另一种方式?

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() );
}

使用Linq to XML不是更简单吗?我在你的问题中没有看到一个确切的模式,但可能是这样的:

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() );
}