如何获得正则表达式匹配的确切位置?

时间:2018-04-08 08:12:05

标签: c#

例如假设我有一个文本字符串

What is the value of pn in 1 ;/
This is a test 12./ lop

我想获得正则表达式匹配的正确行位置\d\s?[.,;:]\s?/。我怎样才能做到这一点 我试过了

string text = @"What is the value of pn in 1 ;/
This is a test 12./ lop";
    string pattern = @"\d\s?[.,;:]\s?/";
    foreach (Match m in Regex.Matches(text, pattern))
    {
        var info=LineFromPos(text,m.Index);
        Console.WriteLine(info+","+m.Index);
    }

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

但代码输出

1,27
2,49

它应该在哪里

1,27
2,16

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

string text = @"What is the value of pn in 1 ;/
This is a test 12./ lop";
string pattern = @"\d\s?[.,;:]\s?/";

var lines = Regex.Split(text, "\r\n|\r|\n").Where(s => s != String.Empty)
    .ToList();
for (int i = 0; i < lines.Count; i++)
{
    foreach (Match m in Regex.Matches(lines[i], pattern))
    {
        Console.WriteLine(string.Format("{0},{1}", i + 1, m.Index));
    }
}

答案 1 :(得分:0)

您目前正在将m.Index视为中的位置,但它实际上是字符串中的位置听起来你可能想要编写一个方法来将字符串索引转换为一个位置(行内的行和索引) - 假设你想将匹配保留在一个字符串中。

例如(使用ValueTuple和C#7语法 - 您可以创建自己的行/列类型):

static (int line, int column) FindPosition(string text, int index)
{
     int line = 0;
     int current = 0;
     while (true)
     {
         int next = text.IndexOf('\n', current);
         if (next > index || next == -1)
         {
             return (line, index - current);
         }
         current = next + 1;
         line++;
     }
}

通过记住上一场比赛的位置,我们可以比这更有效率,但是将它保持为仅接受字符串和索引更简单。

以下是代码中的完整示例:

using System;
using System.Text.RegularExpressions;

static class Int32Extensions
{
    // This doesn't do what you might expect it to!
    public static void Increment(this int x)
    {
        x = x + 1;
    }
}

class Test
{
    static void Main()
    {
        string text = @"What is the value of pn in 1 ;/
This is a test 12./ lop";
        string pattern = @"\d\s?[.,;:]\s?/";
        foreach (Match m in Regex.Matches(text, pattern))
        {
            var position = FindPosition(text, m.Index);
            Console.WriteLine($"{position.line}, {position.column}");
        }
    }


    static (int line, int column) FindPosition(string text, int index)
    {
         int line = 0;
         int current = 0;
         while (true)
         {
             int next = text.IndexOf('\n', current);
             if (next > index || next == -1)
             {
                 return (line, index - current);
             }
             current = next + 1;
             line++;
         }
    }
}

打印输出:

0, 27
1, 16

使用基于0的行号和列号 - 显然,如果您愿意,可以在显示值时添加1。