为什么我在这个 flex 文件中得到的输出不好?



我正在尝试编写一个允许读取systemctl输出的Flex文件。 这个想法是仅显示那些无法启动的服务。 我的代码是:

%{
#include <iostream>
#include <fstream>
using namespace std;
ifstream file;
char* service_name;
int nfs=0;
%}
failed_service      *failed*

%%

failed_service          {nfs++;cout << yytext << endl;}  

%%

int main()
{   

system("systemctl > /var/tmp/system_start.txt");
file.open("/var/tmp/system_start.txt");

yyFlexLexer strm (&file,0);   
strm.yylex();
}

你能告诉我我在哪里失败吗?

输出向我显示了整个systemctl输出。

Flex 可能不是完成此任务的最佳工具。我建议使用grep命令行实用程序。

Flex是用于编写解析器的工具;它的目标是将输入拆分为一系列令牌。它从不搜索模式。在每个输入点,它会尝试所有配置的模式以找到从该点开始的匹配项,并选择最长的可能性。然后,它执行关联的操作,然后在匹配后前进到第一个角色后继续。

如果它与当前输入字符不匹配,则使用默认规则,其模式与任何单个字符匹配,其操作是打印字符。由于唯一的规则永远不会匹配,因此使用此默认规则将整个输入一次复制到输出一个字符。

它绝不是面向线的。您可以使用显式模式将输入拆分为行,但这些都不会自动发生。

如果你打算使用 flex,你至少需要学习一点关于正则表达式的知识。*failed*不是有效的正则表达式;在正则表达式中,*运算符表示它所遵循的事物的零次或多次重复,因此它不能出现在模式的开头。 (*failed*中的第二个*是有效的,但表示"零或多个ds",这不是你的意思。您可能会将正则表达式与 shell 路径名扩展("通配")混淆,其中*表示"除/以外的零个或多个字符"。

在任何情况下,*failed*都不是您在该 flex 文件中匹配的模式。模式是failed_service,这是一个有效的正则表达式,它与自身匹配。您之前定义了相当不必要的宏failed_service,但扩展宏的 flex 语法是{macro-name}。如果您设法扩展了该宏,flex 将报告无效模式。但是,弹性文件中不需要宏;您可以简单地将模式本身放置在规则中。

在 flex 手册中简要描述了 flex 接受的正则表达式的语法,但它假定对这些概念有一定的基本熟悉。该手册还解释了 flex 文件格式和匹配算法。

尽管如此,我真的认为你最好通过grep管道传输systemctl的输出(例如systemctl | grep -Fw failed)。Grep是面向线的,针对此类任务进行了高度优化,并且不需要您提出一组涵盖所有可能性的模式。

最新更新