在纯文本中解析占位符的最佳做法是什么?

时间:2016-04-01 17:04:18

标签: c# .net replace contains

我需要用纯文本解决大量占位符(大约250个)。

占位符定义为%ThisIsAPlaceholder%,例如%EmailSender%

现在它有点令人毛骨悚然:代码也应该处理不区分大小写的占位符。因此,%EmailSender%%EMAILSENDER%%emailsender%是相同的占位符。我觉得这很复杂。

我的第一个方法是:

public string ResolvePlaceholders(string text)
{
    var placeholders = new IEnumerable<string>
    {
        "%EmailSender%",
        "%ErrorMessage%",
        "%ActiveUser%"
    };

    var resolvedText = text;

    foreach(var placeholder in placeholders)
    {
        if(!replacedText.Contains(placeholder))
            continue;

        var value = GetValueByPlaceholder(placeholder);

        resolvedText = resolvedText.Replace(placeholder, value);
    }


    return resolvedText;
}

但是......正如您可能注意到的那样,我无法处理案例中的占位性占位符。 此外,我检查每个占位符(如果它在文本中使用)。使用&gt;时一篇文章中有200个单词,大约有10千字,我认为这个解决方案不是很快。

如何以更好的方式解决这个问题?支持不区分大小写的占位符的解决方案将不胜感激。

2 个答案:

答案 0 :(得分:1)

对于您的案例,一个非常基本但有效的替代方案将是这样的:

private readonly static Regex regex = new Regex("%(?<name>.+?)%");

private static string Replace(string input, ISet<string> replacements)
{
    string result = regex.Replace(input, m => {

        string name = m.Groups["name"].Value;
        string value;
        if (replacements.Contains(name))
        {
            return GetValueByPlaceholder(name);
        }
        else   
        {
            return m.Captures[0].Value;
        }
    });

    return result;
}

public static void Main(string[] args)
{
    var replacements = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase)
    {
        "EmailSender", "ErrorMessage", "ActiveUser"
    };

    string text = "Hello %ACTIVEUSER%, There is a message from %emailsender%. %errorMessage%";
    string result = Replace(text, replacements);

    Console.WriteLine(result);
}

它将使用正则表达式来浏览输入文本一次。请注意,我们通过传递给我们在Main中构造的HashSet的相等比较器进行不区分大小写的比较。任何无法识别的项目都将被忽略。对于更一般的情况,Replace方法可以使用字典:

private static string Replace(string input, IDictionary<string, string> replacements)
{
    string result = regex.Replace(input, m => {

        string name = m.Groups["name"].Value;
        string value;
        if (replacements.TryGetValue(name, out value))
        {
            return value;
        }
        else   
        {
            return m.Captures[0].Value;
        }
    });

    return result;
}

使用来自不受信任来源(例如,互联网上的用户)的输入上的量词进行匹配时的典型建议是为正则表达式指定匹配超时。您必须捕获抛出的RegexMatchTimeoutException,并在这种情况下执行某些操作。

答案 1 :(得分:0)

正则表达式解决方案

private static string ReplaceCaseInsensitive(string input, string search, string replacement)
{
    string result = Regex.Replace(
        input,
        Regex.Escape(search), 
        replacement.Replace("$","$$"), 
        RegexOptions.IgnoreCase
    );
    return result;
}

非正则表达式解决方案

public static string Replace(this string str, string old, string @new, StringComparison comparison)
{
    @new = @new ?? "";
    if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(old) || old.Equals(@new, comparison))
    return str;
    int foundAt;
    while ((foundAt = str.IndexOf(old, 0, StringComparison.CurrentCultureIgnoreCase)) != -1)
    str = str.Remove(foundAt, old.Length).Insert(foundAt, @new);
    return str;
}

似乎是一个重复的问题/答案 String.Replace ignoring case