我必须从ASCII文本文件中解析一些表.这是一个部分样本:
QSMDRYCELL 11.00 11.10 11.00 11.00 -.90 11 11000 1.212
RECKITTBEN 192.50 209.00 192.50 201.80 5.21 34 2850 5.707
RUPALIINS 150.00 159.00 150.00 156.25 6.29 4 80 .125
SALAMCRST 164.00 164.75 163.00 163.25 -.45 80 8250 13.505
SINGERBD 779.75 779.75 770.00 773.00 -.89 8 95 .735
SONARBAINS 68.00 69.00 67.50 68.00 .74 11 3050 2.077
Run Code Online (Sandbox Code Playgroud)
该表由1列文本和8列浮点数组成.我想通过正则表达式捕获每一列.
我对正则表达式很新.这是我提出的错误的正则表达式模式:
(\S+)\s+(\s+[\d\.\-]+){8}
Run Code Online (Sandbox Code Playgroud)
但该模式仅捕获第一列和最后一列.RegexBuddy也会发出以下警告:
您重复了捕获组本身.该组将仅捕获最后一次迭代.在重复组周围放置捕获组以捕获所有迭代.
我已经咨询了他们的帮助文件,但我不知道如何解决这个问题.
如何单独捕获每列?
Tim*_*ker 14
在C#中(从此示例修改):
string input = "QSMDRYCELL 11.00 11.10 11.00 11.00 -.90 11 11000 1.212";
string pattern = @"^(\S+)\s+(\s+[\d.-]+){8}$";
Match match = Regex.Match(input, pattern, RegexOptions.MultiLine);
if (match.Success) {
Console.WriteLine("Matched text: {0}", match.Value);
for (int ctr = 1; ctr < match.Groups.Count; ctr++) {
Console.WriteLine(" Group {0}: {1}", ctr, match.Groups[ctr].Value);
int captureCtr = 0;
foreach (Capture capture in match.Groups[ctr].Captures) {
Console.WriteLine(" Capture {0}: {1}",
captureCtr, capture.Value);
captureCtr++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Matched text: QSMDRYCELL 11.00 11.10 11.00 11.00 -.90 11 11000 1.212
...
Group 2: 1.212
Capture 0: 11.00
Capture 1: 11.10
Capture 2: 11.00
...etc.
Run Code Online (Sandbox Code Playgroud)
不幸的是,您需要重复(\xe2\x80\xa6)8 次才能分别获取每一列。
^(\\S+)\\s+([-.\\d]+)\\s+([-.\\d]+)\\s+([-.\\d]+)\\s+([-.\\d]+)\\s+([-.\\d]+)\\s+([-.\\d]+)\\s+([-.\\d]+)\\s+([-.\\d]+)$\nRun Code Online (Sandbox Code Playgroud)\n\n如果代码可行,您可以首先将这些数字列作为一个整体进行匹配
\n\n>>> rx1 = re.compile(r'^(\\S+)\\s+((?:[-.\\d]+\\s+){7}[-.\\d]+)$', re.M)\n>>> allres = rx1.findall(theAsciiText)\nRun Code Online (Sandbox Code Playgroud)\n\n然后用空格分割列
\n\n>>> [[p] + q.split() for p, q in allres]\nRun Code Online (Sandbox Code Playgroud)\n
如果您想知道出现警告的原因,那是因为您的捕获组匹配多次(如您指定的那样,为 8 次),但捕获变量只能有一个值。它被分配最后一个匹配的值。
正如问题 1313332中所述,使用正则表达式通常不可能检索这些多个匹配项,尽管 .NET 和 Perl 6 对此有一些支持。
该警告建议您可以在整个集合周围放置另一组,如下所示:
(\S+)\s+((\s+[\d\.\-]+){8})
Run Code Online (Sandbox Code Playgroud)
然后您将能够看到所有列,但它们当然不会被分开。因为通常不可能单独捕获它们,所以更常见的目的是捕获所有这些,并且警告有助于提醒您这一点。