Хобрук: Ваш путь к мастерству в программировании

Perl: почему это регулярное выражение парсера работает непоследовательно?

Я столкнулся с другой проблемой, связанной с сайтом, который я пытаюсь очистить.

По сути, я удалил большую часть того, что мне не нужно, из содержимого страницы, и благодаря некоторой помощи, предоставленной здесь удалось выделить нужные мне даты. Большинство из них, кажется, работает нормально, несмотря на некоторые первоначальные проблемы с сопоставлением неразрывного пробела. Однако теперь у меня возникли трудности с окончательным регулярным выражением, которое предназначено для разделения каждой строки данных на поля. Каждая строка представляет цену индекса цен акций. Поля в каждой строке:

  1. Имя произвольной длины, состоящее из символов латинского алфавита и иногда запятой или амперсанда, без цифр.
  2. Число с двумя цифрами после запятой (абсолютное значение индекса).
  3. Число с двумя цифрами после запятой (изменение значения).
  4. Число с двумя цифрами после запятой, за которым следует знак процента (процентное изменение значения).

Вот пример строки до разделения: «Рыболовство, сельское и лесное хозяйство243,45-1,91-0,78% горнодобывающая промышленность360,74-4,15-1,14% строительство465,36-1,01-0,22% продукты питания783,2511,281,46% текстиль и одежда412,070,540. 13% Целлюлозно-бумажная промышленность333,31-0,29-0,09% Химическая промышленность729.406.010,83% "

Регулярное выражение, которое я использую для разделения этой строки, таково:

$mystr =~ s/\n(.*?)(\d{1,4}\.\d{2})(\-?\d{1,3}\.\d{2})(.*?%)\n/\n$1 == $2 == $3 == $4\n/ig;

Иногда это работает, но не в другое время, и я не могу понять, почему это должно быть. (Двойные знаки равенства в приведенном ниже примере используются, чтобы сделать разделение поля более заметным.)

Fishery, Agriculture & Forestry == 243.45 == -1.91 == -0.78%
Mining360.74-4.15-1.14%
Construction == 465.36 == -1.01 == -0.22%
Foods783.2511.281.46%

Я думал, что знак минус был проблемой для тех индексов, которые видели отрицательное изменение в цене индекса, но иногда это работает, несмотря на знак минус.

В. Почему последнее регулярное выражение, показанное ниже, не может последовательно разделить поля?

Ниже приведен пример кода.

#!/usr/bin/perl -w
use strict;
use LWP::Simple;
use HTML::Tree;

my $url_full = "http://www.tse.or.jp/english/market/STATISTICS/e06_past.html";

my $content = get($url_full);
# get dates:
(my @dates) = $content =~ /(?<=dateFormat\(')\d{4}\/\d{2}\/\d{2}(?='\))/g;
foreach my $date (@dates) { # convert to yyyy-mm-dd
    $date =~ s/\//-/ig;
}
my $tree = HTML::Tree->new();
$tree->parse($content);
my $mystr = $tree->as_text;

$mystr =~ s/\xA0//gi; # remove non-breaking spaces
# remove first chunk of text:
$mystr =~
  s/^(TSE.*?)IndustryIndexChange ?/IndustryIndexChange\n$dates[0]\n\n/gi;
$mystr =~ s/IndustryIndexChange ?/IndustryIndexChange/ig;
$mystr =~ s/IndustryIndexChange/Industry Index Change\n/ig;
$mystr =~ s/% /%\n/gi; # percent symbol is market for end of line
# indicate breaks between days:
$mystr =~ s/Stock.*?IndustryIndexChange/\nDAY DELIMITER\n/gi;
$mystr =~ s/Exemption from Liability.*$//g; # remove boilerplate at bottom

# and here's the problem regex...
# try to split it:
$mystr =~
  s/\n(.*?)(\d{1,4}\.\d{2})(\-?\d{1,3}\.\d{2})(.*?%)\n/\n$1 == $2 == $3 == $4\n/ig;

print $mystr;

  • Я предполагаю, что числовые столбцы начинают свою жизнь с чего-то между ними. Но к тому времени, когда мы доберемся до их извлечения, все числа будут смешаны вместе с (надеюсь) фиксированным форматированием, которое поможет нам разделить их. Не было бы намного проще, если бы вы оставили разделительные символы? 08.02.2012
  • Справедливое замечание. Цифры изначально были в 5 разных таблицах, поэтому нужно было либо попытаться проанализировать/сохранить каждую таблицу, либо вывести текст с помощью HTML::Tree, и я выбрал последнее. Поскольку поля довольно регулярные, я не думал, что это будет проблемой, и теоретически я до сих пор не думаю, что это должно быть проблемой. Однако на практике... 08.02.2012

Ответы:


1

Кажется, это делает каждый второй.

Я предполагаю, что ваши записи имеют один \n между ними, но ваш шаблон начинается и заканчивается \n. Таким образом, окончательные \n в первом совпадении потребляют \n, необходимые второму совпадению для поиска второй записи. Конечным результатом является то, что он поднимает каждую вторую запись.

Возможно, вам лучше заключить шаблон в ^ и $ (вместо \n и \n) и использовать флаг m на s///.

08.02.2012
  • Спасибо, это до бешенства очевидно, когда я смотрю на это. Должен существовать какой-то закон регулярных выражений, который гласит, что вероятность решения проблемы с регулярными выражениями обратно пропорциональна времени, затраченному на просмотр регулярных выражений. 08.02.2012

  • 2

    Проблема в том, что у вас есть \n как в начале, так и в конце регулярного выражения.

    Рассмотрим что-то вроде этого:

    $s = 'abababa';
    $s =~ s/aba/axa/g;
    

    это установит $s в axabaxa, не axaxaxa, потому что есть только два непересекающихся вхождения aba.

    08.02.2012
  • Спасибо, hochgurgler опередил вас, но я оценил ваш пример. 08.02.2012

  • 3

    Моя интерпретация (псевдокод) -

    one   = [a-zA-Z,& ]+
    two   = \d{1,4}.\d\d
    three = <<two>>
    four  = <<two>>%
    
    regex = (<<one>>)(<<two>>)(<<three>>)(<<four>>)
          = ([a-zA-Z,& ]+)(\d{1,4}.\d\d)(\d{1,4}.\d\d)(\d{1,4}.\d\d%)
    

    Однако вам уже представлены «структурированные» данные в виде HTML. Почему бы не воспользоваться этим?

    Синтаксический анализ HTML в Perl ссылается на MOJO для синтаксического анализа на основе DOM в Perl, и если нет серьезных причин производительности , я настоятельно рекомендую такой подход.

    08.02.2012
  • Обычно лучше медленно получить правильный ответ, чем быстро получить неправильный. 10.02.2012
  • Новые материалы

    Как я могу подписаться на тему изображений в ROS Matlab и получить изображение RGB?
    Привет, Пожалуйста, как я могу извлечь изображение из сообщения ROS Image, за которым следует imshow? Я уже подписался на правильную тему, но message.getData() дает мне объект..

    Понимание СТРУКТУРЫ ДАННЫХ И АЛГОРИТМА.
    Что такое структуры данных и алгоритмы? Термин «структура данных» используется для описания того, как данные хранятся, а алгоритм используется для описания того, как данные сжимаются. И данные, и..

    Как интегрировать модель машинного обучения на ios с помощью CoreMl
    С выпуском новых функций, таких как CoreML, которые упростили преобразование модели машинного обучения в модель coreML. Доступная модель машинного обучения, которую можно преобразовать в модель..

    Создание успешной организации по науке о данных
    "Рабочие часы" Создание успешной организации по науке о данных Как создать эффективную группу по анализу данных! Введение Это обзорная статья о том, как создать эффективную группу по..

    Технологии и проблемы будущей работы
    Изучение преимуществ и недостатков технологий в образовании В быстро меняющемся мире технологии являются решающим фактором в формировании будущего работы. Многие отрасли уже были..

    Игорь Минар из Google приедет на #ReactiveConf2017
    Мы рады сообщить еще одну замечательную новость: один из самых востребованных спикеров приезжает в Братиславу на ReactiveConf 2017 ! Возможно, нет двух других кланов разработчиков с более..

    Я собираюсь научить вас Python шаг за шагом
    Привет, уважаемый энтузиаст Python! 👋 Готовы погрузиться в мир Python? Сегодня я приготовил для вас кое-что интересное, что сделает ваше путешествие более приятным, чем шарик мороженого в..