获取匹配模式的行号。

12

我使用这段代码来检查一个字符串是否存在于我加载到内存中的文本文件中

foreach (Match m in Regex.Matches(haystack, needle))
    richTextBox1.Text += "\nFound @ " + m.Index;
正则表达式返回了出现匹配的位置,但我想知道行号是多少?

正则表达式返回了出现匹配的位置,但我想知道行号是多少?

4个回答

12

最佳解决方案是调用一个方法,仅在匹配发生时获取行号。 这样如果检查了多个文件并且使用带有 \n 的正则表达式将不会受到太大影响。我在stackoverflow上找到了这个方法:

    public int LineFromPos(string input, int indexPosition)
    {
        int lineNumber = 1;
        for (int i = 0; i < indexPosition; i++)
        {
            if (input[i] == '\n') lineNumber++;
        }
        return lineNumber;
    }

6
你可以先将文本分成几行,然后对每一行应用正则表达式,但是如果 needle 包含换行符,则此方法无法奏效。
var lines = haystack.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
for(int i=0; i <lines.Length; i++)
{
    foreach (Match m in Regex.Matches(lines[i], needle))
        richTextBox1.Text += string.Format("\nFound @ line {0}", i+1)
}

我认为一个更有吸引力的选项是使用StringReader作为查找文本,并使用ReadLine()方法读取行,而不是用分隔符来切割。 - Jeff Mercado
真 - 我假设haystack已经加载到内存中,如果没有,对于更长的文件绝对会优先使用File.ReadLines() - BrokenGlass

1
要做到这一点,我进行了以下操作...
  • Read file contents into buffer
  • Use regex to match all carriage returns in the file and note there index in a list of carriage returns

    private static List<CarriageReturn> _GetCarriageReturns( string data )
    {
        var carriageReturns = new List<CarriageReturn>();
    
        var carriageReturnRegex = new Regex( @"(?:([\n]+?))", RegexOptions.IgnoreCase | RegexOptions.Singleline );
        var carriageReturnMatches = carriageReturnRegex.Matches( data );
        if( carriageReturnMatches.Count > 0 )
        {
            carriageReturns.AddRange( carriageReturnMatches.Cast<Match>().Select( match => new CarriageReturn
            {
                Index = match.Groups[1].Index,
            } ).ToList() );
        }
    
        return carriageReturns;
    }
    
  • Use my regex on the file and for every match do something like this LineNumber = carriageReturns.Count( ret => ret.Index < match.Groups[1].Index ) + 1

所以基本上我会计算出在匹配之前发生的回车符数量并加1。

0
    foreach (Match m in Regex.Matches(haystack, needle))
    {
        int startLine = 1, endLine = 1;
        // You could make it to return false if this fails.
        // But lets assume the index is within text bounds.
        if (m.Index < haystack.Length)
        {
            for (int i = 0; i <= m.Index; i++)
                if (Environment.NewLine.Equals(haystack[i]))
                    startLine++;
            endLine = startLine;

            for (int i = m.Index; i <= (m.Index + needle.Length); i++)
                if (Environment.NewLine.Equals(haystack[i]))
                    endLine++;
        }

        richTextBox1.Text += string.Format(
"\nFound @ {0} Line {1} to {2}", m.Index, startLine, endLine);

如果针穿过一条线,那么这段代码实际上不会起作用,但这是因为正则表达式没有识别到。

编辑:也许你可以将文本中的换行符替换为空格,并在那里应用正则表达式,这段代码仍然可以工作,如果针掉落在一条线上,它仍然会被找到:

Regex.Matches(haystack.Replace(Environment.NewLine, " "), needle)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接