如何从字符串中数字的特定位置获取第N个数字 - 正则表达式

时间:2014-07-16 17:07:06

标签: c# regex vb.net

288007  327920  374740 000368   044575  082865 680798
717374  755879  811106  855460  920577  953515  996819 ......

我有一个包含数千个6位数字的字符串,我希望借助正则表达式在第N个数字后提取第N个数字。

假设我需要在第4个数字之后提取三个数字然后结果应为044575 082865 680798

另一个例子如果我需要在第10个数字后提取2个数字,那么结果应为855460 920577

我不知道这是否可以使用正则表达式,我认为FOR EACH语句可能适用于我的情况。

我只能使用下面的代码提取每个六位数字。

Dim NumberMatchCollection As MatchCollection = Regex.Matches("String containing numbers", "(?<!\d)\d{6}(?!\d)")
For Each NumberMatch As Match In NumberMatchCollection

   Dim ItemNumber As String = NumberMatch.Value

Next

编辑: 我无法保证每个分隔符都是单个空格,双空格,制表符或其他内容。我可以保证数字长度总是6,用空格或标签分隔。

4 个答案:

答案 0 :(得分:2)

使用数学会不会更简单?

第四个数字后面的三个数字是字符(7 * 4)+(7 * 3)

答案 1 :(得分:1)

扩展我的评论。这假设实际数据是等分的。

如果每个数字都有6位数字,中间有空格。然后第四个数字的位置将是(6 + 1)* 4,如果你想要3个数字,你只需要获取(6 + 1)* 3个字符。

    Dim str As String

    str = "288007 327920 374740 000368 044575 082865 680798 717374 755879 811106 855460 920577 953515 996819"

    Dim startingNumber As Integer = 4
    Dim amountToFetch As Integer = 3

    ' 7 = [size of each number] + [delimiter length]
    ' 7 = 6 + 1

    Console.WriteLine(str.Substring(7 * startingNumber, 7 * amountToFetch))
    Console.ReadLine()

答案 2 :(得分:0)

你可以.Split()字符串并在结果数组上使用LINQ扩展方法:

// some test data...
var rand = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10000; i++)
{
    sb.Append(i.ToString("000000") + ((rand.Next(5)==1) ? "  ": "\t"));
}
string s = sb.ToString();

string portion = string.Join("  ", s.Split(new [] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries).Skip(10).Take(3));

Console.WriteLine(portion); // outputs "000011  000012  000013"

注意:对于第一个号码,您需要.Skip(0)

但是如果您的字符串是刚性格式,则显示(假设空格的变量数是拼写错误,感谢@ErikE),Coenraad计算所需字符串开头位置的方法以及需要多少个字符会更有效率。我会把它留给Coenraad扩展这个答案,因为可能采取分数是不公平的。

我试过并试图让regex方法一直很快,但我发现它强烈依赖于你想要检索的数字:

enter image description here

对于想要测试它的人,我在表单上放置了一个默认图表并使用了这段代码:

Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Windows.Forms.DataVisualization
Imports System.Windows.Forms.DataVisualization.Charting

Public Class Form1

    Sub DoStuff()

        Dim ser1 As New Series With {.Name = "String.Split"}
        Dim ser2 As New Series With {.Name = "RegEx"}

        Dim sb As New StringBuilder()

        For i As Integer = 1 To 10000
            sb.Append(i.ToString("000000") + "  ")
        Next
        Dim s As String = sb.ToString()

        Dim sw As New Stopwatch()

        Dim itemsToTake As Integer = 50

        For firstItem = 1 To 9000 Step 100

            sw.Restart()

            Dim portion As String = String.Join(" ", s.Split({" "c}, StringSplitOptions.RemoveEmptyEntries).Skip(firstItem - 1).Take(itemsToTake))

            sw.Stop()
            ser1.Points.AddXY(firstItem -1, sw.ElapsedTicks)

            Dim pattern = "^(?:\d+\s+){" + (firstItem - 1).ToString() + "}((\d+)\s+){" + itemsToTake.ToString() + "}"
            Dim re = New Regex(pattern)

            sw.Restart()
            Dim matches = re.Matches(s)
            Dim cs = matches(0).Groups(0).Captures
            sw.Stop()
            ser2.Points.AddXY(firstItem - 1, sw.ElapsedTicks)

        Next

        Chart1.Series.Clear()
        Chart1.Series.Add(ser1)
        Chart1.Series(0).ChartType = SeriesChartType.Line
        Chart1.Series.Add(ser2)
        Chart1.Series(1).ChartType = SeriesChartType.Line

        Chart1.ChartAreas(0).AxisX.IsMarginVisible = False
        Chart1.ChartAreas(0).AxisX.Title = "First item to retrieve"
        Chart1.ChartAreas(0).AxisY.Title = "Time taken"

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        DoStuff()

    End Sub

End Class

答案 3 :(得分:0)

如果你想要一个正则表达式和c#解决方案,下面的代码在第四个数字示例之后执行3个数字。

        var st = @"288007  327920  374740 000368   044575  082865 680798
                  717374  755879  811106  855460  920577  953515  996819";
        var pattern = @"^(\d+\s+){4}((?<x>\d+)\s+){3}";
        var matches = Regex.Matches(st,pattern,RegexOptions.Singleline);
        foreach (Capture m in matches[0].Groups["x"].Captures)
            Console.WriteLine("value={0}", m.Value);

(编辑:在下面的每个评论中删除了一个组)