不确定为什么在使用包含正则表达式模式(涉及捕获组)的字典时 Regex.Replace() 不起作用

2024-03-12

所以我试图编写一种使用正则表达式将“100 美分”替换为“100 美分”的方法。我使用的模式是 (\d+)(¢)。最重要的是,我还尝试替换其他东西,所以我需要一个字典数据结构来保存所有这些正则表达式模式作为键,以及我想要替换它们的值作为字典值。

到目前为止我的代码是这样的:

        var replacementsMap = new Dictionary<string, string>()
        {
            {@"(\d+)(¢)", "$1 cents"}
        };

字典中还会有更多内容,但为了简单起见,我只添加一个模式值对。 我使用反向引用让第一个捕获组后面带有“cents”而不是符号。

例如:5 美分 -> 5 美分

要替换,我这样做:

        string input = "100¢";
        Console.WriteLine(input); //showing original input


        var regex = new Regex(String.Join("|",replacementsMap.Keys));

        var newStr = regex.Replace(input, m => replacementsMap[m.Value]);
        Console.WriteLine(newStr); //showing new input

我得到的错误是这样的,我不太确定我的实现哪里出了问题:

Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key '100¢' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Program.<>c__DisplayClass1_0.<Main>b__0(Match m) in Program.cs:line 79
   at System.Text.RegularExpressions.Regex.<>c.<Replace>b__99_0(ValueTuple`5& state, Match match)
   at System.Text.RegularExpressions.Regex.RunAllMatchesWithCallback[TState](String inputString, ReadOnlySpan`1 inputSpan, Int32 startat, TState& state, MatchCallback`1 callback, RegexRunnerMode mode, Boolean reuseMatchObject)
   at System.Text.RegularExpressions.Regex.RunAllMatchesWithCallback[TState](String input, Int32 startat, TState& state, MatchCallback`1 callback, RegexRunnerMode mode, Boolean reuseMatchObject)   
   at System.Text.RegularExpressions.Regex.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat)
   at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator)
   at Program.Main() in Program.cs:line 79

问题是,当您有匹配项时,该匹配项不包含有关匹配的原始模式的信息。因此,您无法在字典中进行查找,因为您没有在字典中用作键的模式。

解决方案:将模式组合为一个时,用命名的捕获组包围每个模式。名称基于模式列表中模式的索引。

然后,您可以从匹配信息中获取该名称,使用自动生成的名称从列表中检索原始模式和替换模式,并将单个模式应用于匹配的值。

示例代码:

string input = "I have 5$ and 4€ and 6¢";

// Use a List instead of Dictionary so we can retrieve the entries by index
List<(string pattern, string replacement)> replacementInstructions = new List<(string pattern, string replacement)> {
    (@"(\d+)(¢)", "$1 cents"),
    (@"(\d+)(€)", "$1 euros"),
    (@"(\d+)(\$)", "$1 dollars"),
};

// Create combined pattern with auto-named groups
StringBuilder builder = new StringBuilder();

for(int i=0; i < replacementInstructions.Count; i++)
{
    if(i > 0) builder.Append("|");

    var (pattern, _) = replacementInstructions[i];

    string groupName = "GN" + i;
    builder.Append("(?<" + groupName + ">" + pattern + ")");
}

string combinedPattern = builder.ToString();
Console.WriteLine("Combined Pattern: " + combinedPattern);

// Declare callback that will do the replacement
MatchEvaluator evaluator = (Match match) =>
{
    // Get named group that matched and its name
    Group group = (from Group g in match.Groups
                   where g.Success &&
                   g.Name.StartsWith("GN")
                   select g).First();
    string groupName = group.Name;

    // Get number from groupname 
    // and then entry from replacementInstructions based on number
    string numberString = groupName.Substring(2);
    int number = int.Parse(numberString);
    var (pattern, replacement) = replacementInstructions[number];

    // Apply replacement pattern on match
    return Regex.Replace(match.Value, pattern, replacement);
};


// Replace
string result = Regex.Replace(input, combinedPattern, evaluator);

Console.WriteLine("Result: " + result);

Output:

Combined Pattern: (?<GN0>(\d+)(¢))|(?<GN1>(\d+)(€))|(?<GN2>(\d+)(\$))
Result: I have 5 dollars and 4 euros and 6 cents
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

不确定为什么在使用包含正则表达式模式(涉及捕获组)的字典时 Regex.Replace() 不起作用 的相关文章

  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • ASP.NET Web API 客户端 ProgressMessageHandler Post 任务卡在 WinForm 应用程序中

    我在用着HttpClient and ProgressMessageHandler来自MS ASP NET Web API 客户端库 http nuget org packages Microsoft AspNet WebApi Clien
  • 防止 boost::asio::io_context 在空轮询调用时停止

    此代码调用发布的句柄 boost asio io context ioc boost asio post ioc std cout lt lt lol lt lt std endl ioc poll 而这并没有 boost asio io
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • 动态生成的控件 ID 返回为 NULL

    我可以在 Page PreInit 函数中创建动态控件 如何检索控件及其 ID 我的 C 代码用于创建动态控件之一 var btn new WebForms Button btn Text btn ID Addmore btn Click
  • vs2008 c#:Facebook.rest.api如何使用它来获取好友列表?

    如何在此基础上取得进一步的进步 获取好友列表的下一步是什么 string APIKey ConfigurationManager AppSettings API Key string APISecret ConfigurationManag
  • 检查 RoutedEvent 是否有任何处理程序

    我有一个自定义 Button 类 当单击它时 打开特定窗口 它总是执行相同的操作 我添加了一个可以在按钮的 XAML 中分配的 Click 事件 就像常规按钮一样 当它被单击时 我想执行 Click 事件处理程序 如果已分配 否则我想执行默
  • 将标量添加到特征矩阵(向量)

    我刚刚开始使用 Eigen 库 无法理解如何向所有矩阵成员添加标量值 假设我有一个矩阵 Eigen Matrix3Xf mtx Eigen Matrix3Xf Ones 3 4 mtx mtx 1 main cxx 104 13 error
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • IEnumerable.Except 不起作用,那么我该怎么办?

    我有一个 linq to sql 数据库 非常简单 我们有 3 个表 项目和用户 有一个名为 User Projects 的连接表将它们连接在一起 我已经有了一个获得的工作方法IEnumberable
  • 正则表达式将单词的开头和结尾与元音匹配

    我正在尝试以下操作Regex aeiou aeiou 但它不起作用 我测试了 abcda 并且不匹配 它应该只是 aeiou aeiou 额外的 您需要第二个字符是一个文字点 例如 a hello 但由于您的测试用例 abcda 不包含这样
  • 每个数据库多个/单个 *.edmx 文件

    我有一个通过 ADO net 数据服务与数据库交互的项目 数据库很大 近 150 个具有依赖关系的表 该项目几年前开始 当时使用的是数据集 现在我们正在转向实体模型关系 由于我们添加了更多需要使用的表 该模型正在不断增长 这是管理这一切的正
  • 您是否将信息添加到每个 .hpp/.cpp 文件的顶部? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 创建新的 C 头文件 源文件时 您会在顶部添加哪些信息 例如 您是否添加日期 您的姓名 文件描述等 您是否使用结构化格式来存储此信息 e g F
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐