换句话说,RegExp不匹配

时间:2018-12-17 10:24:41

标签: c regex lex

大家好,我正在用lex测试一个正则表达式,以从html中找到html中的产品ID。我不知道为什么当它读取文件女巫包含的内容:

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

它可以工作,但是如果内容像这样:

aaaaaa 4,7由5 estrellas组成的 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 :(得分:1)

由(f)lex生成的词法分析器的预期用例是将输入拆分为一系列原始的“令牌”,每个令牌具有一定的句法意义。它们不会搜索正则表达式,因为它们假定输入的每个部分都将与您的词法描述中的某些模式匹配。

因此,每次词法分析器检查输入时,它将选择提供最佳 match 的模式。匹配是从当前输入点开始的与模式匹配的字符序列,而最佳匹配是与最长序列匹配的字符序列。 (如果有两个或多个匹配相同最长序列的模式,则模式列表中的第一个被认为是最佳模式。)

考虑到这一点,请考虑输入会发生什么情况

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也可能不是您的用例的理想工具。您并没有真正说出用例是什么,所以我不会以一种或另一种方式做出任何假设。

无论如何,您应该花几分钟阅读documentation on flex patterns。该页面上未描述的任何正则表达式语法都不能与(f)lex一起使用,无论它是否与正则表达式库或在线正则表达式检查器一起使用。特别是,.*?不会 not 给您一个非贪婪的匹配,就像在许多正则表达式库中一样。 (F)lex不实现非贪婪匹配(因为它不执行任何回溯),并且它认为.*?是任意数字的可选(?)外观,包括零重复( *),除了换行符(.)以外的任何字符。将重复设为可选是无效的,因为重复已经匹配了零次重复。因此,模式<.*?> << / kbd>到同一行的最后一个> 匹配。那可能不是您想要的。

您可能还不想使用<span+,它与 << / kbd>匹配,后跟字母 a p a ,然后是任意数量的 n (只要有至少一个)。换句话说,它将匹配<span<spann<spannnnnnnnnnn等。

答案 1 :(得分:0)

感谢您的回答,问题在于{valoraciones}与第一个规则发生冲突之后的三个规则。因此,我找不到其他单词之间的任何单词,例如,我想用aaaaadogaaaa在文本中找到狗,这与我一开始所说的狗原因不符。

相关问题