Регулярное выражение: повторяющиеся группы захвата

Мне нужно проанализировать некоторые таблицы из текстового файла 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 

Таблица состоит из 1 столбца текста и 8 столбцов чисел с плавающей запятой. Я хотел бы захватить каждый столбец с помощью регулярного выражения.

Я довольно новичок в регулярных выражениях. Вот неисправный шаблон регулярного выражения, с которым я столкнулся:

 (\S+)\s+(\s+[\d\.\-]+){8} 

Но шаблон фиксирует только первый и последний столбцы. RegexBuddy также выдает следующее предупреждение:

Вы повторили захват группы. Группа будет захватывать только последнюю итерацию. Поместите группу захвата вокруг повторяющейся группы, чтобы захватить все итерации.

Я проконсультировал их файл справки, но я не знаю, как это решить.

Как я могу захватить каждый столбец отдельно?

В 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++; } } } 

Выход:

 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. 

К сожалению, вам нужно повторить (…) 8 раз, чтобы получить каждый столбец отдельно.

 ^(\S+)\s+([-.\d]+)\s+([-.\d]+)\s+([-.\d]+)\s+([-.\d]+)\s+([-.\d]+)\s+([-.\d]+)\s+([-.\d]+)\s+([-.\d]+)$ 

Если код возможен, вы можете сначала сопоставить эти числовые столбцы в целом

 >>> rx1 = re.compile(r'^(\S+)\s+((?:[-.\d]+\s+){7}[-.\d]+)$', re.M) >>> allres = rx1.findall(theAsciiText) 

затем разделите столбцы пробелами

 >>> [[p] + q.split() for p, q in allres] 

Если вы хотите знать, для чего появляется предупреждение, это связано с тем, что ваша группа захвата имеет несколько совпадений (8, как вы указали), но переменная захвата может иметь только одно значение. Ему присваивается последнее значение.

Как описано в вопросе 1313332 , получение этих множественных совпадений, как правило, невозможно с регулярным выражением, хотя .NET и Perl 6 имеют некоторую поддержку для него.

Предупреждение подсказывает, что вы могли бы разместить другую группу вокруг всего набора, например:

 (\S+)\s+((\s+[\d\.\-]+){8}) 

Затем вы сможете увидеть все столбцы, но, разумеется, они не будут разделены. Поскольку их вообще невозможно фиксировать отдельно, более распространенное намерение состоит в том, чтобы зафиксировать все это, и предупреждение поможет вам в этом.