2

我有一个用于组装自动文件名的字符串模式。该模式可能包含几个属性,例如:

[UserName]
[ItemName]
[ItemId]

等等......当要创建名称时,我获取属性的值并在模式中替换它们以获得所需的名称。例如:

var propertyDict = new Dictionary<string, string>()
{
     ["[UserName]"] = "John Smit",
     ["[ItemName]"] = "Berry 47",
     ["[ItemId]"] = "123456",
};

var namingPattern = "[UserName] @ [ItemName] (id: [ItemId])";

// Expected result  "John Smit @ Berry 47 (id: 123456)"

只需一个foreach循环即可轻松解决此问题,在该循环中,我将字典键的任何匹配项替换为其各自的值:

 foreach (var kvp in propertyDict)
 {
      namingPattern = namingPattern.Replace(kvp.Key, kvp.Value);
 }

困扰我的是用户选择了一个可能破坏逻辑的意外名称的情况。考虑以下情况:

var propertyDict = new Dictionary<string, string>()
{
     ["[UserName]"] = "[ItemName]", // Username matches with one of the placeholders
     ["[ItemName]"] = "Berry 47",
     ["[ItemId]"] = "123456",
};

var namingPattern = "[UserName] @ [ItemName] (id: [ItemId])";

// Expected result  "[ItemName] @ Berry 47 (id: 123456)"
// Actual result    "Berry 47 @ Berry 47 (id: 123456)"

我找到了一种通过使用 RegEx 来解决此问题的方法。我的想法是"\[[a-zA-Z]+\]"在进行任何字符串替换之前匹配所有可能的占位符 (),然后通过首先检查匹配字符串的索引来开始替换。但是,如果将来其他人必须通过此逻辑,则阅读起来太冗长且烦人。有什么想法和建议吗?提前致谢!

4

1 回答 1

-2

您可以使用Regex.Replace一次通过更新所有匹配项。

这样,您就不会覆盖任何已经进行的替换:

var namingPattern = "[UserName] @ [ItemName] (id: [ItemId])";
var regexPattern = string.Join("|", propertyDict.Keys.Select(Regex.Escape));
// \[UserName]|\[ItemName]|\[ItemId]

var fileName = Regex.Replace(namingPattern, regexPattern,
    match => propertyDict[match.Value]);

并且为了避免使用Regex.Escape键,您可以使用大括号代替:

var propertyDict = new Dictionary<string, string>()
{
     ["{UserName}"] = "John Smit",
     ["{ItemName}"] = "Berry 47",
     ["{ItemId}"] = "123456",
};

var namingPattern = "{UserName} @ {ItemName} (id: {ItemId})";
var regexPattern = string.Join("|", propertyDict.Keys);
// {UserName}|{ItemName}|{ItemId}

var fileName = Regex.Replace(namingPattern, regexPattern,
    match => propertyDict[match.Value]);
于 2020-08-28T12:53:49.230 回答