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,用空格或标签分隔。
答案 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方法一直很快,但我发现它强烈依赖于你想要检索的数字:
对于想要测试它的人,我在表单上放置了一个默认图表并使用了这段代码:
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);
(编辑:在下面的每个评论中删除了一个组)