获取匹配模式的行号

时间:2022-09-13 07:39:29

I use this code to check if a string exist in a text file that I loaded into memory

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

foreach (Match m in Regex.Matches(haystack, needle))
    richTextBox1.Text += "\nFound @ " + m.Index;

The regex returns the positions where a match occurred but I want to know the line number?

正则表达式返回匹配发生的位置,但我想知道行号?

3 个解决方案

#1


5  

You can split your text into lines first and apply your RegEx to each line - of course that doesn't work if needle contains a NewLine:

您可以先将文本拆分为行,然后将RegEx应用于每一行 - 当然,如果针包含NewLine,则无效:

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)
}

#2


5  

The best solution would be to call a method that gets the line number only if a match occurs. This way the performance is not much affected if multiple files were checked and the regexp with \n will work. Found this method somewhere on *:

最好的解决方案是调用仅在匹配发生时获取行号的方法。这样,如果检查了多个文件并且带有\ n的正则表达式将起作用,则性能不会受到太大影响。在*上的某处发现了这个方法:

    public int LineFromPos(string S, int Pos)
    {
        int Res = 1;
        for (int i = 0; i <= Pos - 1; i++)
            if (S[i] == '\n') Res++;
        return Res;
    }

#3


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);

Won't actually work if the needle crosses a line, but that's because the regex does not recognize that.

如果针穿过一条线,实际上不会起作用,但这是因为正则表达式无法识别。

Edit maybe you can replace the endlines in the text with spaces and apply the regex there, this code would still work and if the needle falls over a line it would still be found:

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

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

#1


5  

You can split your text into lines first and apply your RegEx to each line - of course that doesn't work if needle contains a NewLine:

您可以先将文本拆分为行,然后将RegEx应用于每一行 - 当然,如果针包含NewLine,则无效:

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)
}

#2


5  

The best solution would be to call a method that gets the line number only if a match occurs. This way the performance is not much affected if multiple files were checked and the regexp with \n will work. Found this method somewhere on *:

最好的解决方案是调用仅在匹配发生时获取行号的方法。这样,如果检查了多个文件并且带有\ n的正则表达式将起作用,则性能不会受到太大影响。在*上的某处发现了这个方法:

    public int LineFromPos(string S, int Pos)
    {
        int Res = 1;
        for (int i = 0; i <= Pos - 1; i++)
            if (S[i] == '\n') Res++;
        return Res;
    }

#3


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);

Won't actually work if the needle crosses a line, but that's because the regex does not recognize that.

如果针穿过一条线,实际上不会起作用,但这是因为正则表达式无法识别。

Edit maybe you can replace the endlines in the text with spaces and apply the regex there, this code would still work and if the needle falls over a line it would still be found:

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

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