c#中的Regex如何只替换捕获组而不替换非捕获组

本文关键字:替换 中的 Regex | 更新日期: 2023-09-27 18:03:56

我正在使用c#在Visual studio 2013 Express中编写正则表达式。我试图在每个包含单词和!@#$%^&*()_-的字符串周围加上单引号,除了:

  • 空()
  • notempty ()
  • currentdate ()
  • 任何带有单引号的字符串

这是我的正则表达式和它做什么的一个例子:https://regex101.com/r/nI1qP0/1

我只想在捕获组周围加上单引号,而不触及非捕获组。我知道这可以通过环顾来实现,但是我不知道怎么做。

c#中的Regex如何只替换捕获组而不替换非捕获组

你可以使用这个正则表达式:

(?:'[^']*'|(?:'b(?:(?:not)?empty|currentdate)'(')|and|or|not))|([!@#$%^&*_.'w-]‌​+)
这里忽略的匹配不会被捕获,要引用的字可以使用Match.Groups[1] 检索。然后,您可以在Match.Groups[1]周围添加引号,并根据需要替换整个输入。

RegEx演示

您需要使用匹配求值器或回调方法。关键在于,您可以在此方法中检查匹配和捕获的组,并根据您的模式决定采取什么操作。

所以,添加这个回调方法(如果调用方法是非静态的,可能是非静态的):

public static string repl(Match m)
{
    return !string.IsNullOrEmpty(m.Groups[1].Value) ?
        m.Value.Replace(m.Groups[1].Value, string.Format("'{0}'", m.Groups[1].Value)) :
        m.Value;
}

然后,用匹配求值器(=回调方法)重载Regex.Replace:

var s = "'This is not captured' but this is and not or empty() notempty() currentdate() capture";
var rx = new Regex(@"(?:'[^']*'|(?:'b(?:(?:not)?empty|currentdate)'(')|and|or|not))|([!@#$%^&*_.'w-]+)");
Console.WriteLine(rx.Replace(s, repl));

注意,您可以使用lambda表达式缩短代码:

Console.WriteLine(rx.Replace(s, m => !string.IsNullOrEmpty(m.Groups[1].Value) ?
    m.Value.Replace(m.Groups[1].Value, string.Format("'{0}'", m.Groups[1].Value)) :
    m.Value));

参见IDEONE demo

没有尝试忽略包含单词和!@#$%^&*()_-的字符串,我只是将它们包含在搜索中,在两端放置一个额外的单引号,然后删除两个单引号的所有实例,如下所示:

 // Find any string of words and !@#$%^&*()_- in and out of quotes.
 Regex getwords = new Regex(@"(^(?!and'b)(?!or'b)(?!not'b)(?!empty'b)(?!notempty'b)(?!currentdate'b)(['w!@#$%^&*())_-]+)|((?!and'b)(?!or'b)(?!not'b)(?!empty'b)(?!notempty'b)(?!currentdate'b)(?<='W)(['w!@#$%^&*()_-]+)|('['w's!@#$%^&*()_-]+')))", RegexOptions.IgnoreCase);
 // Find all cases of two single quotes
 Regex getQuotes = new Regex(@"('')");
 // Get string from user
 Console.WriteLine("Type in a string");
 string search = Console.ReadLine();
 // Execute Expressions.
 search = getwords.Replace(search, "'$1'");
 search = getQuotes.Replace(search, "'");