千家信息网

linux的中怎么安装和使用flex

发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,这篇"linux的中怎么安装和使用flex"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这
千家信息网最后更新 2025年12月01日linux的中怎么安装和使用flex

这篇"linux的中怎么安装和使用flex"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"linux的中怎么安装和使用flex"文章吧。

在linux中,flex是一个词法分析工具,能够识别文本中的词法模式;Flex读入给定的输入文件,如果没有给定文件名的话,则从标准输入读取,从而获得一个关于需要生成的扫描器的描述。

本教程操作环境:linux5.9.8系统、Dell G3电脑。

flex:词法分析器

flex是一个词法分析器。用来将一个.l文件生成一个.c程序文件。即生成一个词法分析器。然后读取输入,和正则表达式匹配,再执行相应的动作,实现了程序的功能。我们可以发现flex实现在程序外部就可以接受输入的功能。

Flex是一个生成扫描器的工具,能够识别文本中的词法模式。Flex 读入给定的输入文件,如果没有给定文件名的话,则从标准输入读取,从而获得一个关于需要生成的扫描器的描述。此描述叫做规则,由正则表达式和 C代码对组成。Flex 的输出是一个 C 代码文件--lex.yy.c--其中定义了yylex() 函数。编译输出文件可以生成一个可执行文件。当运行可执行文件的时候,它分析输入文件,为每一个正则表达式寻找匹配。当发现一个匹配时,它执行与此正则表达式相关的C代码。Flex 不是GNU工程,但是GNU为Flex 写了手册。

用法

  • 安装 flex

sudo apt-get install flex//或者下载相应版本的安装文件安装
  • 然后新建一个文本文件,输入以下内容:

%%[0-9]+  printf("?");#       return 0;.       ECHO;%%int main(int argc, char* argv[]) {    yylex();    return 0;}int yywrap() {     return 1;}

将此文件另存为 hide-digits.l 。注意此文件中的 %% 必须在本行的最前面(即 %% 前面不能有任何空格)。

  • 之后,在终端输入:

flex hide-digits.l
  • 此时目录下多了一个 "lex.yy.c" 文件,把这个 C 文件编译并运行一遍:

 gcc -o hide-digits lex.yy.c./hide-digits

然后在终端不停的敲入任意键并回车,可以发现,敲入的内容中,除数字外的字符都被原样的输出了,而每串数字字符都被替换成 ? 了。最后敲入 # 后程序退出了。如下:

eruiewdkfjeruiewdkfj1245?fdsaf4578fdsaf?...#
  • 当在命令行中运行 flex 时,第二个命令行参数(此处是 hide-digits.l )是提供给 flex 的分词模式文件, 此模式文件中主要是用户用正则表达式写的分词匹配模式,用flex 会将这些正则表达式翻译成 C 代码格式的函数 yylex ,并输出到 lex.yy.c 文件中,该函数可以看成一个有限状态自动机。

  • 当在命令行中运行 flex 时,第二个命令行参数(此处是 hide-digits.l )是提供给 flex 的分词模式文件, 此模式文件中主要是用户用正则表达式写的分词匹配模式,用flex 会将这些正则表达式翻译成 C 代码格式的函数 yylex ,并输出到 lex.yy.c 文件中,该函数可以看成一个有限状态自动机。

  • 下面再来详细解释一下 hide-digits.l 文件中的代码,首先第一段是:

%%[0-9]+  printf("?");#       return 0;.       ECHO;%%
  • flex 模式文件中,用%% 和 %%做分割, 上面分割的内容被称为 规则(rules),本文件中每一行都是一条规则,每条规则由 匹配模式(pattern) 和 事件(action) 组成, 模式在前面,用正则表达式表示,事件在后面,即 C 代码。每当一个模式被匹配到时,后面的 C 代码被执行。

  • flex 会将本段内容翻译成一个名为 yylex 的函数,该函数的作用就是扫描输入文件(默认情况下为标准输入),当扫描到一个完整的、最长的、可以和某条规则的正则表达式所匹配的字符串时,该函数会执行此规则后面的 C 代码。如果这些 C 代码中没有 return 语句,则执行完这些 C 代码后, yylex 函数会继续运行,开始下一轮的扫描和匹配。

  • 当有多条规则的模式被匹配到时, yylex 会选择匹配长度最长的那条规则,如果有匹配长度相等的规则,则选择排在最前面的规则。

int main(int argc, char *argv[]) {    yylex();    return 0;}int yywrap() { return 1; }
  • 第二段中的 main 函数是程序的入口, flex 会将这些代码原样的复制到 lex.yy.c 文件的最后面。最后一行的 yywrap 函数, flex 要求有这么一个函数。

示例

word-spliter.l

%{#define T_WORD 1int numChars = 0, numWords = 0, numLines = 0;%}WORD([^ \t\n\r\a]+)%%\n{ numLines++; numChars++; }{WORD}{ numWords++; numChars += yyleng; return T_WORD; }<>{ return 0; }.{ numChars++; }%%int main() {int token_type;while (token_type = yylex()) {printf("WORD:\t%s\n", yytext);}printf("\nChars\tWords\tLines\n");printf("%d\t%d\t%d\n", numChars, numWords, numLines);return 0;}int yywrap() {return 1;}

本例中使用到了 flex 提供的两个全局变量 yytext 和 yyleng,分别用来表示刚刚匹配到的字符串以及它的长度

编译执行

flex word-spliter.lgcc -o word-spliter lex.yy.c./word-spliter < word-spliter.l输出:WORD:       %{WORD:       #define...WORD:       }Chars       Words   Lines470 70      27

可见此程序其实就是一个原始的分词器,它将输入文件分割成一个个的 WORD 再输出到终端,同时统计输入文件中的字符数、单词数和行数。此处的 WORD 指一串连续的非空格字符。

扩展

(1) 列出所需的所有类型的 token;

(2) 为每种类型的 token 分配一个唯一的编号,同时写出此 token 的正则表达式;

(3) 写出每种 token 的 rule (相应的 pattern 和 action )。

第 1 类为单字符运算符,一共 15 种:

+ * - / % = , ; ! < > ( ) { }

第 2 类为双字符运算符和关键字,一共 16 种:

<=, >=, ==, !=, &&, ||void, int, while, if, else, return, break, continue, print, readint

第 3 类为整数常量、字符串常量和标识符(变量名和函数名),一共 3 种。

拓展后

%{#include "token.h"int cur_line_num = 1;void init_scanner();void lex_error(char* msg, int line);%}/* Definitions, note: \042 is '"' */INTEGER             ([0-9]+)UNTERM_STRING       (\042[^\042\n]*)STRING              (\042[^\042\n]*\042)IDENTIFIER          ([_a-zA-Z][_a-zA-Z0-9]*)OPERATOR            ([+*-/%=,;!<>(){}])SINGLE_COMMENT1     ("//"[^\n]*)SINGLE_COMMENT2     ("#"[^\n]*)%%[\n]                { cur_line_num++;                       }[ \t\r\a]+          { /* ignore all spaces */               }{SINGLE_COMMENT1}   { /* skip for single line comment */    }{SINGLE_COMMENT2}   { /* skip for single line commnet */    }{OPERATOR}          { return yytext[0];         }   "<="                { return T_Le;              }">="                { return T_Ge;              }"=="                { return T_Eq;              }"!="                { return T_Ne;              }"&&"                { return T_And;             }"||"                { return T_Or;              }"void"              { return T_Void;            }"int"               { return T_Int;             }"while"             { return T_While;           }"if"                { return T_If;              }"else"              { return T_Else;            }"return"            { return T_Return;          }"break"             { return T_Break;           }"continue"          { return T_Continue;        }"print"             { return T_Print;           }"readint"           { return T_ReadInt;         }{INTEGER}           { return T_IntConstant;     }{STRING}            { return T_StringConstant;  }{IDENTIFIER}        { return T_Identifier;      }<>             { return 0; }{UNTERM_STRING}     { lex_error("Unterminated string constant", cur_line_num);  }.                   { lex_error("Unrecognized character", cur_line_num);        }%%int main(int argc, char* argv[]) {    int token;    init_scanner();    while (token = yylex()) {        print_token(token);        puts(yytext);    }    return 0;}void init_scanner() {    printf("%-20s%s\n", "TOKEN-TYPE", "TOKEN-VALUE");    printf("-------------------------------------------------\n");}void lex_error(char* msg, int line) {    printf("\nError at line %-3d: %s\n\n", line, msg);}int yywrap(void) {    return 1;}

上面这个文件中,需要注意的是,正则表达式中,用双引号括起来的字符串就是原始字符串,里面的特殊字符是不需要转义的,而双引号本身必须转义(必须用 \" 或 \042 ),这是 flex 中不同于常规的正则表达式的一个特性。

除单字符运算符外的 token 的编号则在下面这个 token.h 文件,该文件中同时提供了一个 print_token 函数,可以根据 token 的编号打印其名称。

#ifndef TOKEN_H#define TOKEN_Htypedef enum {    T_Le = 256, T_Ge, T_Eq, T_Ne, T_And, T_Or, T_IntConstant,    T_StringConstant, T_Identifier, T_Void, T_Int, T_While,    T_If, T_Else, T_Return, T_Break, T_Continue, T_Print,    T_ReadInt} TokenType;static void print_token(int token) {    static char* token_strs[] = {        "T_Le", "T_Ge", "T_Eq", "T_Ne", "T_And", "T_Or", "T_IntConstant",        "T_StringConstant", "T_Identifier", "T_Void", "T_Int", "T_While",        "T_If", "T_Else", "T_Return", "T_Break", "T_Continue", "T_Print",        "T_ReadInt"    };    if (token < 256) {        printf("%-20c", token);    } else {        printf("%-20s", token_strs[token-256]);    }}#endif

makefile

out: scannerscanner: lex.yy.c token.hgcc -o $@ $

以上就是关于"linux的中怎么安装和使用flex"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

文件 函数 模式 正则 表达式 输入 代码 字符 规则 内容 输出 程序 词法 生成 字符串 分析 运行 命令 就是 分析器 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 重庆管理软件开发有哪些 封闭式网络安全训练 服务器代码管理软件 吉林省教育厅网络安全 基因的抑制剂数据库 南宁鸿图互联网科技有限公司 国家网络安全宣传周青少年日 sql数据库安装引擎失败 数据库连接数php 中央网信办网络安全招生 腾讯云数据库认证级别 安徽大学网络安全考研考什么 redis多开使数据库混乱 将要率领一个软件开发小组 网络技术计算目的网络 天津华为服务器维修调试费用 网络安全法第三条第二项 网络安全秘钥是哪个密码 四年级网络安全作文100 广州h5软件开发公司 奉贤区本地网络技术欢迎咨询 我的世界1.17.7服务器推荐 php软件开发价格 服务器的功率 2u 无线网络技术教程考试题 墨博云舟用的服务器是什么牌子 服务器桌面显示图片图标 静安区上门软件开发电话多少 组策略设置代理服务器地址设置 四年级网络安全作文100
0