草庐IT

C# 排序并放回 Regex.matches

coder 2023-10-23 原文

是否有任何方法可以使用 RegEx.Matches 以不同的(字母顺序)顺序查找和写回匹配值?

现在我有这样的东西:

var pattern = @"(KEY `[\w]+?` \(`.*`*\))";
var keys = Regex.Matches(line, pattern);

Console.WriteLine("\n\n");
foreach (Match match in keys)
{
    Console.WriteLine(match.Index + " = " + match.Value.Replace("\n", "").Trim());
}

但我真正需要的是获取 table.sql 转储并按字母顺序对现有索引进行排序,示例代码:

line = "...PRIMARY KEY (`communication_auto`),\n  KEY `idx_current` (`current`),\n  KEY `idx_communication` (`communication_id`,`current`),\n  KEY `idx_volunteer` (`volunteer_id`,`current`),\n  KEY `idx_template` (`template_id`,`current`)\n);"

谢谢 杰


更新: 谢谢,m.buettner 解决方案为我提供了可以继续前进的基础知识。遗憾的是,我不太擅长 RegEx,但我最终得到了我认为仍然可以改进的代码:

...
//sort INDEXES definitions alphabetically
if (line.Contains("  KEY `")) line = Regex.Replace(
    line,
    @"[ ]+(KEY `[\w]+` \([\w`,]+\),?\s*)+",
    ReplaceCallbackLinq
);

static string ReplaceCallbackLinq(Match match) 
{
    var result = String.Join(",\n  ",
        from Capture item in match.Groups[1].Captures
        orderby item.Value.Trim()
        select item.Value.Trim().Replace("),", ")")
    );
    return "  " + result + "\n";
}


更新: 还有一种情况,当索引字段长于 255 个字符时,mysql 将索引修剪到 255,并这样写:

KEY `idx3` (`app_property_definition_id`,`value`(255),`audit_current`),

因此,为了也匹配这种情况,我不得不更改一些代码: 在 ReplaceCallbackLinq 中:

select item.Value.Trim().Replace("`),", "`)")

和正则表达式定义:

@"[ ]+(KEY `[\w]+` \([\w`(\(255\)),]+\),?\s*)+",

最佳答案

这不能单独使用正则表达式来完成。但是您可以使用回调函数并利用 .NET 的独特功能,即使用同一捕获组捕获多个事物。这样您就可以避免使用 Matches 并自己写回所有内容。相反,您可以使用内置的Replace 功能。我下面的示例简单地对 KEY 短语进行排序并将它们放回原样(因此它除了在 SQL 语句中对短语进行排序外什么都不做)。如果您想要不同的输出,您可以通过捕获模式的不同部分并在最后调整 Join 操作来轻松实现。

首先我们需要一个匹配评估器来传递回调:

MatchEvaluator evaluator = new MatchEvaluator(ReplaceCallback);

然后我们编写一个正则表达式来一次匹配整个索引集,在捕获组中捕获索引名称。我们把它放在带有求值器的 Replace 的重载中:

output = Regex.Replace(
    input,
    @"(KEY `([\w]+)` \(`[^`]*`(?:,`[^`]*`)*\),?\s*)+",
    evaluator
);

现在在大多数语言中这将没有用,因为由于重复捕获组 1 将始终仅包含捕获的第一个或最后一个内容(与捕获组 2 相同)。但幸运的是,您使用的是 C#,而 .NET 的正则表达式引擎只是一个强大的野兽。那么让我们看一下回调函数以及如何使用多次捕获:

static string ReplaceCallback(Match match)
{
    int captureCount = match.Groups[1].Captures.Count;
    string[] indexNameArray = new string[captureCount];
    string[] keyBlockArray = new string[captureCount];
    for (int i = 0; i < captureCount; i++)
    {
        keyBlockArray[i] = match.Groups[1].Captures[i].Value;
        indexNameArray[i] = match.Groups[2].Captures[i].Value;
    }
    Array.Sort(indexNameArray, keyBlockArray);
    return String.Join("\n  ", keyBlockArray);
}

match.Groups[i].Captures 让我们可以访问单个组的多个捕获。由于这些是 Capture 对象,目前看起来并不是很有用,我们从它们的值构建两个字符串数组。然后我们使用 Array.Sort 根据一个数组的值(被视为键)对两个数组进行排序。作为“键”,我们使用表名的捕获。作为“值”,我们使用一个完整的 KEY ..., block 的完整捕获。这将按名称对完整 block 进行排序。然后我们可以简单地将 block 连接在一起,添加之前使用的空白分隔符并返回它们。

关于C# 排序并放回 Regex.matches,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13317864/

有关C# 排序并放回 Regex.matches的更多相关文章

  1. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  2. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  3. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  4. ruby-on-rails - 需要帮助最大化多个相似对象中的 3 个因素并适当排序 - 2

    我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night

  5. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

    我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

  6. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  7. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

    例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

  8. ruby-on-rails - 尝试为 Rails 中的用户名验证编写 REGEX - 2

    我正在尝试用Ruby(Rails)编写一个正则表达式,以便用户名的字符仅包含数字和字母(也没有空格)。我有这个正则表达式,/^[a-zA-Z0-9]+$/,但它似乎没有用,我在Rails中收到一个错误,说“The如果正则表达式使用多行anchor(^或$),这可能会带来安全风险。您是要使用\A和\z,还是忘记添加:multiline=>true选项?"我的user.rb模型中此实现的完整代码是:classUser我做错了什么以及如何修复此正则表达式,使其仅对数字和字母有效而不对空格有效?谢谢。 最佳答案 简短回答:使用/\A[a-z

  9. ruby-on-rails - 如何对对象数组进行排序? - 2

    我有一个对象如下:[{:id=>2,:fname=>"Ron",:lname=>"XXXXX",:photo=>"XXX"},{:id=>3,:fname=>"Dain",:lname=>"XXXX",:photo=>"XXXXXXX"},{:id=>1,:fname=>"Bob",:lname=>"XXXXXX",:photo=>"XXXX"}]我想按fname排序,不区分大小写,所以它会导致编号:1,3,2我该如何排序?我正在尝试:@people.sort!{|x,y|y[:fname]x[:fname]}但这没有任何效果。 最佳答案

  10. Ruby Regex,获取所有可能的匹配项(不截断字符串) - 2

    我遇到了ruby​​正则表达式的问题。我需要找到所有(可能重叠的)匹配项。这是问题的简化:#Simpleexample"Hey".scan(/../)=>["He"]#Actualresults#Withoverlappingmatchestheresultshouldbe=>["He"],["ey"]我尝试执行并获得所有结果的正则表达式如下所示:"aaaaaa".scan(/^(..+)\1+$/)#Thislooksformultiplesof(here)"a"biggerthanonethat"fills"theentirestring."aa"*3=>true,"aaa"*2=

随机推荐