На самом деле не существует возможного решения для регулярных выражений, которое работает для произвольного числа табличных данных и помещает каждую ячейку в отдельную обратную ссылку.Это связано с тем, что для обратных ссылок вам нужно иметь отдельную открытую скобку для каждого обратного ссылки, которую вы хотите создать, и вы не знаете, сколько у вас ячеек.
Нет ничего плохого в использовании зацикливания того или иного рода для извлечения данных.Например, на последнем в Perl это будет так, поскольку $tr
уже содержит нужную вам строку:
@td = ( $tr =~ m{<td.*?>(.*?)</td>}sg );
Теперь $td[0]
будет содержать первые <td>
, $td[1]
будет содержать второй и т. д. Если вам нужен двумерный массив, вы можете заключить его в такой цикл, чтобы заполнить новую переменную @cells
:
our $table; # assume has full table in it
my @cells;
while(my($tr) =~ $table = m{<tr.*?>(.*?)</tr>}sg) {
push @cells, [ $tr =~ m{<td.*?>(.*?)</td>}sg ];
}
Теперь вы можете сделать дваадресация, допускающая $cells[0][0]
и т. д. Внешний явный цикл обрабатывает таблицу по очереди, а внутренний неявный цикл вытягивает все ячейки.
Это будет работать с постоянными выборочными данными.ты показал.Если это достаточно хорошо для вас, тогда отлично.Используйте его и двигайтесь дальше.
Что с этим может быть не так?
Однако в ваших шаблонах есть довольно много предположений относительно содержания ваших данных, которые я не делаюзнаю, что вы знаете.Во-первых, обратите внимание, как я использовал /s
, чтобы он не застревал на новых строках.
Но главная проблема в том, что минимальные совпадения не всегда вполне соответствуют тому, что вы хотите здесь.По крайней мере, не в общем случае.Иногда они не так минимальны, как вы думаете, соответствуют больше, чем вы хотите, а иногда они просто не соответствуют.
Например, шаблон, подобный <i>(.*?)</i>
, получит больше, чем вы хотите, если строка:
<i>foo<i>bar</i>ness</i>
Поскольку вы в конечном итоге сопоставите строку <i>foo<i>bar</i>
.
Другая распространенная проблема (не считая необычных) состоит в том, что шаблон, подобный <tag.*?>
, может слишком мало совпадать, например, с
<img alt=">more" src="somewhere">
Теперь, если вы используете упрощенный <img.*?>
на этом, вы бы только захватили <img alt=">
, что, конечно, неправильно.
Я думаю, что последняя серьезная проблема заключается в том, что вы должны вообще игнорировать некоторые вещи при разборе.Простейшая демонстрация этого встроенного комментария (также <script>
, <style>, and
CDATA`), поскольку у вас может быть что-то вроде
<i> some <!-- secret</i> --> stuff </i>
, которое будет сбрасывать что-то вроде <i>(.*?)</i>
.
Конечно, есть способы обойти это.После того, как вы это сделали, и это действительно немало усилий, вы обнаружите, что создали себе настоящий парсер, полностью с множеством вспомогательной логики, а не с одним паттерном.
Даже тогда вы обрабатываете только правильно сформированные входные строки.Восстановление после ошибок и мягкий сбой - совершенно другое искусство.