在Regex匹配的地方获得整条线

本文关键字:方获得 Regex | 更新日期: 2023-09-27 18:28:48

我有一些多行文本,我想找到包含特定单词的行。

在当前的实现中,我只得到单词,但我想得到整行。这是代码:

var finder = new Regex(@"(^|'W)" + Regex.Escape(wordToFind) + @"('W|$)", RegexOptions.IgnoreCase);
 foreach (var match in finder.Matches(multilineString))
 {
      //match should be the whole line
 }

示例:

If Request.QueryString("bar") <> "" Then
    Set bar= foo("baz")
Else
    Set bar= foo("baz2")
End If

如果我寻找foo,我应该得到:

Set bar= foo("baz")
Set bar= foo("baz2")

我没有实现正则表达式,也不太熟悉正则表达式,如果有人能给我一些提示,让我继续研究,我将不胜感激。

感谢

在Regex匹配的地方获得整条线

您可以尝试使用以下正则表达式:

Regex regex = new Regex(@"^.*?'W" + Regex.Escape(wordToFind) + @"'W.*?$");

^与字符串或行的开头匹配,末尾的$与字符串或线的末尾匹配
.*?匹配所有字符(但尽可能少),'W(大写"W")匹配任何非单词字符(既不是字母也不是数字的字符)。

或者,如果您希望单词仅由空格分隔,则可以使用's(小写"s")而不是'W

这是Regex的一个很好的参考。

你可以这样做

string[] lines = multilinestring.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
List<string> validString = new List<string>();
foreach(string s in lines)
{
   if(finder.Match(s).Success)
   {
      validString.Add(s);
   }
}

试试看,应该能

List<string> lines = multilinestring.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList();
List<string> validString =  lines.Where(x => finder.IsMatch(x)).ToList();

Nolonar的解决方案没有考虑一行以所需单词开头或结尾的可能性。

此外,您需要记住,^$锚与整个字符串的开始/结束匹配,除非您通过RegexOptions.Multiline选项使它们与边界匹配。

因此,提取包含一个完整单词的所有行的正确的仅正则表达式解决方案是

var finder = new Regex($@"^.*?(?<!'w){Regex.Escape(wordToFind)}(?!'w).*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
// Or, in order to avoid getting CR at the end of the extracted lines
// var finder = new Regex($@"^.*?(?<!'w){Regex.Escape(wordToFind)}(?!'w)[^'r'n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
var results = finder.Matches(multilineString).Cast<Match>().Select(x => x.Value); // Use x.Value.Trim() to trim the result

请注意,您可以通过使用内联修饰符(?im):将RegexOptions.IgnoreCase | RegexOptions.Multiline合并到模式本身来"收缩"代码一点

var finder = new Regex($@"(?im)^.*?(?<!'w){Regex.Escape(wordToFind)}(?!'w).*");
var finder = new Regex($@"(?im)^.*?(?<!'w){Regex.Escape(wordToFind)}(?!'w)[^'r'n]*"); 
                          ^^^^^

查看regex演示

图案详细信息

  • ^—线路起点
  • .*?-除了换行符之外的任何0+个字符,尽可能少(*?是一个懒惰的、非贪婪的量词)
  • (?<!'w)-左侧单词边界
  • {Regex.Escape(wordToFind)}-wordToFind字符串的转义版本
  • (?!'w)-右侧单词边界
  • .*-除了换行符之外的任何0+个字符,尽可能多(*是贪婪的量词)注意.与.NET正则表达式中的回车'r匹配,因此我建议.Trim()使用提取的值。或者使用[^'r'n]*来匹配除CR和LF之外的0个或多个字符