高级regex.replace处理

时间:2013-05-29 00:40:51

标签: c# regex

我使用正则表达式 MatchEvaluator 委托来处理格式字符串,例如“时间:%t,字节:%b”将用时间戳替换“%t”“%b”带字节数。不用说,还有很多其他选择!

为此,我使用:

    Regex regex = new Regex("%((?<BytesCompleted>b)|(?<BytesRemaining>B)|(?<TimeStamp>t))");
    string s = "%bhello%t(HH:MM:SS)%P";
    string r = regex.Replace(s, new MatchEvaluator(ReplaceMatch));

string ReplaceMatch(Match m)
{
    ... Handle the match replacement.
}

如果我可以在委托中使用正则表达式组名称(甚至数字,我不是那么挑剔)而不是与原始匹配进行比较以找出它是匹配的,那会更好:

string ReplaceMatch(Match m)
{
    ...
    case "%t":
    ...
    case "%b";
    ...
}

非常丑陋;我想用

string ReplaceMatch(Match m)
{
    ...
    case "BytesCompleted":
    ...
    case "TimeStamp":
    ...
}

我无法通过调试器或谷歌看到任何明显的东西。有任何想法吗?

3 个答案:

答案 0 :(得分:0)

能够在交换机中使用组名称会很高兴;遗憾的是Group对象没有Name属性(基类Capture也没有),所以你能做的最好的是:

string ReplaceMatch(Match m)
{
    if (m.Groups["BytesCompleted"].Success) // ...
    else if (m.Groups["BytesRemaining"].Success) // ...
    // ...
}

答案 1 :(得分:0)

您可以使用Regex.GroupNameFromNumber实例方法,遗憾的是,匹配评估程序方法需要引用Regex对象:

string ReplaceMatch(Match m)
{
    for (int i = 0; i < m.Groups.Count; i++)
    {
        string groupName = _regex.GroupNameFromNumber(i);
        switch (groupName)
        {
            case "BytesCompleted":
                // do something
                break;
            case "BytesRemaining":
                // do somehting else
                break;
            ...
        }
    }
    ...
}

这里我假设可以通过Regex变量访问_regex对象。

答案 2 :(得分:0)

我们需要将新浪和詹姆斯两者结合起来。答案。我们需要枚举组以获取索引并检查组成功。然后我们使用索引来获取组名。我已经扩展了一个自我解释测试,它使用字典来替换匹配的子字符串。通过在框架中对组名称的更多支持,这将变得更加容易。

另请参阅另一个可能适合您的答案:https://stackoverflow.com/a/1381163/481812

[Test]
public void ExploreRxReplace()
{
    var txt = " ABC XYZ DEF ";
    var exp = " *** XYZ xxx ";
    var rx = new Regex(@"\s*(?<abc>ABC)\s*|\s*(?<def>DEF)\s*");
    var data = new Dictionary<string, string>() { { "abc", "***" }, { "def", "xxx" } };

    var txt2 = rx.Replace(txt, (m) =>
    {
        var sb = new StringBuilder();
        var pos = m.Index;

        for (var idx = 1; idx < m.Groups.Count; idx++)
        {
            var group = m.Groups[idx];

            if (!group.Success)
            {
                // ignore non-matching group
                continue;
            }

            var name = rx.GroupNameFromNumber(idx);

            // append what's before
            sb.Append(txt.Substring(pos, group.Index - pos));

            string value = null;
            if (group.Success && data.TryGetValue(name, out value))
            {
                // append dictionary value
                sb.Append(value);
            }
            else
            {
                // append group value
                sb.Append(group.Value);
            }

            pos = group.Index + group.Length;
        }

        // append what's after
        sb.Append(txt.Substring(pos, m.Index + m.Length - pos));

        return sb.ToString();
    });

    Assert.AreEqual(exp, txt2);
}