当前位置: 首页 > 知识库问答 >
问题:

.NET正则表达式在一个字符串上匹配/捕获,并在不同字符串上的查找/替换中使用捕获

蒋承教
2023-03-14

我想实现一个功能,即正则表达式匹配一个输入字符串中的各种内容并保存到命名的捕获组,然后使用引用这些捕获的正则表达式替换来修改完全不同的输入字符串。本质上,后一个字符串是来自各种更新源的数据汇编,其中第一个可能是其中之一。

我在一个. NET应用程序中这样做,所以使用Regex对象编译的解决方案是可用的,但是匹配/替换模式字符串是由最终用户在运行时提供的(所以我不能只对MatchEvalue ator重载做一些特定的事情,或者将两个输入字符串合并为一个,而不会非常小心)。

我很难相信这一点,但我还没有找到任何方法在正则表达式实例中保留匹配/捕获,或者将它们传递到替换操作(或者跨原子操作持久或访问捕获的任何其他方法)。到目前为止,我想到的最好的事情是做一个正则表达式。在替换模式上替换为MatchEvaluator,用Match替换例如“$1”。组[1]。价值

有更好的方法吗?谢谢

共有2个答案

谭富
2023-03-14

我对正则表达式很陌生,当我开始编码时,我突然想到为什么它是一个定制的解决方案——因为即使在同一个字符串捕获组中,也不会跨匹配持久存在。

我接受了NetMage的建议,但将其作为正则表达式的扩展方法实现。代替在我看来,这本质上是提供了一个选项,在替换过程中使用传入的实例覆盖替换中每个匹配的可用匹配数据,因此我只针对单个匹配(针对第一个文档作为一个整体)执行此操作,并且如果用户的第一个正则表达式生成多个匹配,则可能会通知用户,因为只有一个用于防止冲突。如果参数类型是CaptureCollection,可能会更直观。

最后,我可能还会实现其余的捕获组选项(例如$$、$'等),以确保完整性。

public static class RegexEx
{
    public static string Replace(this Regex inst, string input, string replacement, Match match)
    {
        replacement = Regex.Replace(replacement, @"(?<!\\)\$(?:(?<Name>\d+)|{(?<Name>\w+)})", m =>
        {
            return match.Groups[m.Groups["Name"].Value].Success ?
                match.Groups[m.Groups["Name"].Value].Value : m.Value;
        });

        return inst.Replace(input, replacement);
    }
}
吕高昂
2023-03-14

这是我的解决方案和示例使用,按照您的建议执行,在替换模式上进行替换。我选择创建字典来存储替换值,尽管这确实需要一些开销。

首先,一些从包含其组的匹配创建字典的方法:

public Dictionary<string,string> CaptureDictionary(Match m) => m.Groups.Cast<Group>().ToDictionary(g => g.Name, g => g.Value);
public Dictionary<string, string> CaptureDictionary(string src, string pat) => CaptureDictionary(Regex.Match(src, pat));

现在,一种方法采用模式字符串,并将所有参考模式(无论是$\d还是${\w})替换为字典中的相应值(如果找到)(否则忽略):

public string Expander(string src, Dictionary<string, string> vals) {
    string expander(Match m) {
        return vals.TryGetValue(m.Groups[1].Value, out var v) ? v : m.Value;
    }
    return Regex.Replace(src, @"\$(?:(?<var>\d+)|{(?<var>\w+)})", expander);
}

现在一个应用Expander两次的方法,首先从匹配模式扩展捕获,然后从之前的字符串匹配模式扩展捕获:

public string DoubleExpander(Match m, string pat, Dictionary<string, string> c1) => Expander(Expander(pat, CaptureDictionary(m)), c1);

现在,您可以编写一个方法,该方法接受一个字符串、一个匹配模式字符串、一个替换模式字符串和一个捕获字典并应用它:

public string ExpandReplace(string src, string pat, string sub, Dictionary<string, string> vals) => Regex.Replace(src, pat, m => DoubleExpander(m, sub, vals));

示例用法:

源字符串定义三个变量的值,pvq,模式提取这些值:

var s1 = "p = 7; v = 12; q = 15;";
var p1 = @"p = (?<p>\d+); v = (?<v>\d+); q = (?<q>\d+);";

var capture1Values = CaptureDictionary(s1, p1);    

第二个替换使用这些捕获变量值在表达式字符串中展开它们:

var s2 = "x = p+v*q";
var pat2 = @"([pvq])";
var sub2 = @"${$1}";

var ans = ExpandReplace(s2, pat2, sub2, capture1Values);

注意:我通常更喜欢扩展方法,所以这是作为扩展的压缩代码:

public static class ReplaceExt {
    public static Dictionary<string, string> CaptureDictionaryFrom(this string src, string pat) => Regex.Match(src, pat).ToCaptureDictionary();
    public static Dictionary<string, string> ToCaptureDictionary(this Match m) => m.Groups.Cast<Group>().ToDictionary(g => g.Name, g => g.Value);
    public static string Expand(this string src, Dictionary<string, string> vals) => Regex.Replace(src, @"\$(?:(?<var>\d+)|{(?<var>\w+)})", m => vals.TryGetValue(m.Groups[1].Value, out var v) ? v : m.Value);
    public static string ExpandReplace(this string src, string pat, string sub, Dictionary<string, string> vals) => Regex.Replace(src, pat, m => sub.Expand(m.ToCaptureDictionary()).Expand(vals));
}

与以前类似地使用:

var s1 = "p = 7; v = 12; q = 15;";
var p1 = @"p = (?<p>\d+); v = (?<v>\d+); q = (?<q>\d+);";
var capture1Values = s1.CaptureDictionaryFrom(p1);

var s2 = "x = p+v*q";
var pat2 = @"([pvq])";
var sub2 = @"${$1}";

var ans = s2.ExpandReplace(pat2, sub2, capture1Values);

 类似资料:
  • https:www.google。com/;ParamName=项目;AccessKey=PDJKJDSJJKNEIOWEMCL/dsjdkhfjf=;值=xyz 在这里,我想用一些虚拟字符串替换值并返回整个字符串。 预期输出:<代码>https:www.google。com/;ParamName=项目;AccessKey=dummyValueHere;值=xyz 是否有人可以通过使用replac

  • 问题内容: 我在用Python将字符串中的数字匹配时遇到麻烦。尽管应该明确匹配,但甚至不匹配 或仅匹配。我的监督在哪里? 问题答案: 阅读文档:http : //docs.python.org/2/library/re.html#re.match 如果在零个或多个字符 开头 的 字符串 您要使用(或)

  • 我试图用正则表达式匹配替换给定的字符。例如,给定以下字符串: 如果你看看你生活中拥有的,你总是会拥有更多。如果你看看你生活中没有的,你永远不会有足够的 我想用“!”替换所有的“t”,只有在字符“ok”和“fe”之间匹配的情况下。 我用这个正则表达式得到“ok”和“fe”之间的匹配: 并且我只能将一个字符与以下正则表达式匹配: 我试图用以下方式转换正则表达式,但它不起作用: 我怎样才能在ok和fe之

  • 我有一根下面这样的弦 现在我希望我的程序验证我的输入是否与字符串“phone”的模式相同 我做了以下工作 没奏效。我也尝试了其他的组合。什么都不起作用。 问题:1。我怎样才能做到这一点,而不使用‘模式’像上面?2.如何用图案做到这一点。我尝试了如下模式 Pattern Pattern=Pattern.compile(“(\d+)”);Matcher match=pattern.Matcher(电话

  • 问题:如何首先捕获两个角色之间的组,然后再匹配匹配组中的角色? 给定输入: 问题1:我想捕获两个角色之间的组,无限次。 正则表达式解决方案: 捕获的群体: 问题2:我想匹配捕获组中的一个字符 尝试正则表达式解决方案1: 尝试的正则表达式解决方案2: 我的问题:以上尝试的解决方案都没有捕获输入字符串中的星号。我如何实现这一点?

  • 我想匹配任何文本中的某些行,在匹配中,我想尽可能频繁地替换某个字符。示例文本: 任何文本和“更多”文本。不要在此处替换引号 CatchThis(此处没有引号,“任何更多文本”,“等等…”)。。。 现在,我想用哈希符号来替换圆括号中的每个引号。预期结果: 任何文本和“更多”文本。不要在此处替换引号 CatchThis(此处没有引号,#没有更多文本#,#等等…#)。。。 匹配线条很容易。这是我的模式: