c# - 如何单独替换组中的每个捕获?

标签 c# .net regex matchevaluator capturecollection

我有一个使用 GroupCollection 的正则表达式它的捕获中的 s 捕获一组 Item Id(可以用逗号分隔,也考虑到最后一个具有单词“and”):

(\bItem #(?<ITEMID>\d+))|(,\s?(?<ITEMID>\d+))|(,?\sand\s(?<ITEMID>\d+))

有没有一种使用 C# 的简单方法 Regex类用 url 替换 ITEMID 数字?现在,我有以下内容:

foreach (Match match in matches)
{
    var group = match.Groups["ITEMID"];
    var address = String.Format(UnformattedAddress, group.Value);

    CustomReplace(ref myString, group.Value, address,
        group.Index, (group.Index + group.Length));
}

public static int CustomReplace(ref string source, string org, string replace,
    int start, int max)
{
    if (start < 0) throw new System.ArgumentOutOfRangeException("start");
    if (max <= 0) return 0;

    start = source.IndexOf(org, start);

    if (start < 0) return 0;

    var sb = new StringBuilder(source, 0, start, source.Length);

    var found = 0;
    while (max-- > 0)
    {
        var index = source.IndexOf(org, start);

        if (index < 0) break;

        sb.Append(source, start, index - start).Append(replace);
        start = index + org.Length;
        found++;
    }

    sb.Append(source, start, source.Length - start);
    source = sb.ToString();

    return found;
}

CustomReplace我在网上找到的方法是一种用字符串源内部的另一个字符串替换一个字符串的简单方法。问题是我确信可能有一种更简单的方法,可能使用 Regex类替换 GroupCollection如有必要。我就是不明白那是什么。谢谢!

示例文本:

Hello the items you are looking for are Item #25, 38, and 45. They total 100 dollars.

25 , 38 ,和45应替换为我正在创建的 URL 字符串(这是一个 HTML 字符串)。

最佳答案

您的模式适用于您的输入,但它确实有一个错误。具体来说,它将匹配输入中逗号或单词 "和 " 之后出现的任何数字。

我继续重写了您的模式以避免这个问题。为了实现这一目标,我实际上使用了两种正则表达式模式。可以使用一种模式来实现这一目标,但它比我选择分享的方法相当复杂且可读性较差。

主要模式是:\bItem #\d+(?:,?\d+)*(?:,? and\d+)? 这里没有使用捕获组,因为我只对匹配项目感兴趣。 (?: ... ) 位是非捕获组。 (?:,?\d+)* 的用法是匹配字符串中间部分的多个逗号分隔值。

一旦项目匹配,我使用 Regex.Replace格式化项目,然后重建字符串以将原始项目与格式化项目交换。

这是一个包含几个不同输入的示例:

string[] inputs =
{
    "Hello the items you are looking for are Item #25, 38, 22, and 45. They total 100 dollars.",
    "... Item #25, 38 and 45. Other numbers 100, 20, and 30 untouched.",
    "Item #25, and 45",
    "Item #25 and 45",
    "Item #25"
};

string pattern = @"\bItem #\d+(?:,? \d+)*(?:,? and \d+)?";
string digitPattern = @"(\d+)";
// $1 refers to the first (and only) group in digitPattern
string replacement = @"<a href=""http://url/$1.html"">$1</a>";

foreach (var input in inputs)
{
    Match m = Regex.Match(input, pattern);
    string formatted = Regex.Replace(m.Value, digitPattern, replacement);
    var builder = new StringBuilder(input)
                        .Remove(m.Index, m.Length)
                        .Insert(m.Index, formatted);
    Console.WriteLine(builder.ToString());
}

如果您需要使用现有方法来格式化 URL,则可以使用接受 MatchEvaluatorRegex.Replace 重载,而不是使用正则表达式替换模式。 。这可以使用 lambda 来实现,并且比 MSDN 文档中显示的繁琐方法更好。

例如,假设您有一个 FormatItem 方法,该方法接受字符串并返回格式化字符串:

public string FormatItem(string item)
{
    return String.Format("-- {0} --", item);
}

要使用 FormatItem,您需要使用以下代码更改早期代码示例中使用的 Regex.Replace 方法:

string formatted = Regex.Replace(m.Value, digitPattern,
                       d => FormatItem(d.Value));

关于c# - 如何单独替换组中的每个捕获?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11267536/

相关文章:

c# - 如何创建 .NET 4 MVC 3 作业/队列系统?

c# - Wpf 渐变等效于 css 渐变

javascript - 使用正则表达式从 javascript 函数返回语句中查找键/值

c# - 如何在没有实例化和销毁的情况下切换游戏对象?

c# - 在 Xamarin 中隐藏软键盘

.net - Nuget 包存储在哪里?

regex - 在一个Perl正则表达式中组合不同的大小写规则

java - 正则表达式,用于从html输出中提取标签之间的内容

c# - 如何检查针对 Sql Server 数据库的 linq 查询结果是否存在数据?

c# - 使 XML 文档引用类的字段