RegExp не соответствует, когда в середине других слов - PullRequest
0 голосов
/ 17 декабря 2018

Привет всем, я тестирую регулярное выражение с помощью lex, чтобы найти идентификатор продукта в html от amazon.Я не знаю, почему, когда он читает файл, который содержит:

<span class="a-icon-alt">4,7 de un máximo de 5 estrellas</span>

, он работает, но если его содержимое выглядит примерно так:

aaaaaa 4,7 максимум 5 оценок bbbbbb

это не так.Есть код с регулярным выражением.

%{
#include <stdio.h>

int nc, np, nl;
void escribir_datos (int dato1, int dato2, int dato3);
%}

productos (<li+[ ]+id=\"result_[0-9]*)+
num_productos [0-9]*
nombre_producto <h2+[ ]+data-attribute=\"([^\"]*)
nombre_final_producto \"[^\"]*\"
precio_producto <span+[ ]+class=\"a-size-base+[ ]+a-color-price+[ ]+s-price+[ ]+a-text-bold\">(.*?)<\/span>
precio_final_producto [0-9]+([,][0-9]+)?
valoraciones  <span+[ ]+class=\"a-icon-alt\">(.*?)<\/span>

%%

{valoraciones}    { nl++; }
[^ \t\n]+   { np++; nc += yyleng; }
[ \t]+      { nc += yyleng; }
\n          { nc++; }
%%

/*----- Sección de Procedimientos --------*/

int main (int argc, char *argv[]) {
  if (argc == 2) {
     yyin = fopen (argv[1], "rt");
     if (yyin == NULL) {
         printf ("El fichero %s no se puede abrir\n", argv[1]);
         exit (-1);
     }
  }
  else yyin = stdin;

nc = np = nl = 0;
yylex ();
escribir_datos(nc,np,nl);

return 0;
}

void escribir_datos (int dato1, int dato2, int dato3) {
printf("Num_char=%d\tNum_words=%d\tNum_lines=%d\n", dato1,dato2,dato3);
}

Спасибо, надеюсь, вы мне поможете.

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Спасибо за ответ, проблема заключалась в том, что три правила после {valoraciones} вызывали конфликт с первым.Так что я не смог найти ни одного слова между другими словами, например, я хочу найти собаку в тексте с aaaaadogaaaa, который не совпадает с собакой из-за того, что я сказал в начале.

0 голосов
/ 18 декабря 2018

Предполагаемый вариант использования лексических анализаторов, сгенерированных (f) lex, состоит в том, чтобы разделить входные данные на серию примитивных «токенов», каждый из которых имеет некоторое синтаксическое значение.Они не ищут регулярных выражений, поскольку предполагают, что каждая часть ввода будет соответствовать некоторому шаблону в вашем лексическом описании.

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

Имея это в виду, рассмотрим, что происходит с входными данными

aaaaaa< span class="a-icon-alt">4,7 de un máximo de 5 estrellas< /span>bbbbbb

Ваш файл имеет четыре шаблона:

{valoraciones}
[^ \t\n]+
[ \t]+
\n

Входные данные не соответствуют {valoraciones}, поскольку этот шаблон соответствует только строке, начинающейся с <</kbd>.Он также не соответствует [ \t]+, потому что он не начинается ни с пробела, ни с табуляции, и аналогично он не соответствует переводу строки.Но это соответствует [^ \t\n]+.Поскольку (f) lex всегда выбирает самое длинное совпадение, а [^ \t\n]+ соответствует любой последовательности символов, кроме пробелов (пробел, табуляция, новая строка), первое совпадение будет aaaaaaa<.

После того, как это совпадение,ввод span..., что означает, что совпадает только третий шаблон ([ \t]+).Он может соответствовать любому количеству пробелов, но есть только один, и это то, что он будет соответствовать.

Итак, ввод будет span class="a-icon-alt">4,7....{valoraciones} все равно не будет совпадать - ввод не начинается с <</kbd> - поэтому мы вернулись к совпадению второго шаблона.

И так далее.

Я думаю, вы должны быть намного яснее (с самим собой) о том, с какими токенами вы пытаетесь сопоставить.Если вы ищете определенные теги HTML, то, вероятно, вы захотите распознать любую последовательность, которая не содержит <</kbd> в качестве токена, а не искать ввод, оканчивающийся символом пробела.Но тогда вам также необходимо принять любой тег в качестве токена, а также конкретные теги, которые вы пытаетесь поймать.

Конечно, также возможно, что (f) lex не идеальный инструмент для вашего случая использования.Вы на самом деле не говорите, какой у вас вариант использования, поэтому я не собираюсь делать какие-либо предположения так или иначе.

В любом случае, вам нужно потратить несколько минут, чтобы прочитать документацию на гибких узорах .Любой синтаксис регулярных выражений, не описанный на этой странице, не будет работать с (f) lex, независимо от того, работает ли он с библиотеками регулярных выражений или онлайн-проверками регулярных выражений.В частности, .*? действительно не дает вам не жадное совпадение, как это было бы во многих библиотеках регулярных выражений.(F) lex не реализует не жадные совпадения (потому что он не производит обратного отслеживания), и он считает .*? необязательным (?) появлением любого числа, включая ноль повторений (*)любого символа, кроме новой строки (.).Задание повторения необязательно, так как повторение уже соответствует нулю повторений.Таким образом, шаблон <.*?> будет соответствовать от <</kbd> до последнего > в той же строке.Это, вероятно, не то, что вы хотите.

Вы также, вероятно, не хотите <span+, что соответствует <</kbd>, за которыми следуют буквы a p a , а затем любое число n (если есть хотя бы один).Другими словами, он будет соответствовать <span, <spann, <spannnnnnnnnnn и многим другим.

...