linux flex是什么

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

linux 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 要求有这么一个函数。

示例

HTML+CSS+jQuery实现Flex悬停滑块 HTML+CSS+jQuery实现Flex悬停滑块

一款HTML+CSS+jQuery实现的Flex悬停滑块特效

HTML+CSS+jQuery实现Flex悬停滑块 131 查看详情 HTML+CSS+jQuery实现Flex悬停滑块

word-spliter.l

%{#define T_WORD 1int numChars = 0, numWords = 0, numLines = 0;%}WORD([^ tnra]+)%%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%sn", yytext);}printf("nCharstWordstLinesn");printf("%dt%dt%dn", 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: 42 is '"' */INTEGER             ([0-9]+)UNTERM_STRING       (42[^42n]*)STRING              (42[^42n]*42)IDENTIFIER          ([_a-zA-Z][_a-zA-Z0-9]*)OPERATOR            ([+*-/%=,;!(){}])SINGLE_COMMENT1     ("//"[^n]*)SINGLE_COMMENT2     ("#"[^n]*)%%[n]                { cur_line_num++;                       }[ tra]+          { /* ignore all spaces */               }{SINGLE_COMMENT1}   { /* skip for single line comment */    }{SINGLE_COMMENT2}   { /* skip for single line commnet */    }{OPERATOR}          { return yytext[0];         }   "="                { 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%sn", "TOKEN-TYPE", "TOKEN-VALUE");    printf("-------------------------------------------------n");}void lex_error(char* msg, int line) {    printf("nError at line %-3d: %snn", line, msg);}int yywrap(void) {    return 1;}

上面这个文件中,需要注意的是,正则表达式中,用双引号括起来的字符串就是原始字符串,里面的特殊字符是不需要转义的,而双引号本身必须转义(必须用 ” 或 42 ),这是 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 $@ $<lex.yy.c: scanner.lflex $<

1.png

相关推荐:《Linux视频教程》

以上就是linux flex是什么的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/262796.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
双出风+6赫兹超低频,一场由中国企业引发的中央空调体验革命
上一篇 2025年11月4日 09:34:17
苹果手机屏幕花屏怎么办
下一篇 2025年11月4日 09:34:18

相关推荐

  • Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程

    Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程

    通过点击Chrome右上角三点菜单,选择“书签”>“显示书签栏”可恢复书签栏;2. 使用Ctrl+Shift+B(Windows)或Command+Shift+B(Mac)快捷键快速切换显示;3. 在设置页面的“外观”中确保“显示书签栏”设为“始终显示”;4. 若无效,可重置浏览器设置以恢复默…

    2026年9月24日 用户投稿
    000
  • sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    Sublime Text的session文件记录了打开的文件、光标位置、代码折叠状态、窗口布局及未保存内容等信息,位于系统特定目录下的Local文件夹中,以JSON格式存储,通过自动保存机制在重启后恢复编辑状态。 Sublime Text 的 session 文件主要用于保存用户当前编辑环境的状态信…

    2026年9月24日 用户投稿
    000
  • LINUX怎么统计一个文件夹下文件的数量_LINUX文件数量统计命令

    使用find命令统计文件数量最准确,如find /path/to/directory -type f | wc -l可递归统计所有普通文件,包含隐藏文件,推荐用于复杂场景。 要统计 Linux 系统中一个文件夹下文件的数量,可以使用多种命令组合来实现。最常用的方法是结合 find、ls 和 wc 命…

    2026年9月24日
    600
  • VSCode如何实现代码热重载 VSCode实时预览开发的高效配置方案

    使用live server扩展实现静态文件的实时预览,保存后浏览器自动刷新;2. 利用现代前端框架(如react、vue)内置的开发服务器(如vite、webpack dev server)实现hmr热模块替换,修改代码后仅更新变动模块而不刷新页面;3. 结合browsersync等工具实现多设备同…

    2026年9月24日
    000
  • 为什么要4k对齐

    早期硬盘的每个扇区以512字节为标准,而新一代硬盘的扇区容量则为4096个字节,即所谓的4k扇区。虽然硬盘标准已经更新,但操作系统仍然使用512字节扇区的标准。为了确保兼容性,硬盘制造商将4k扇区模拟成了512字节扇区。文件系统的块(簇)通常是512字节的倍数,而新系统大多设定为4k的倍数,例如li…

    2026年9月24日
    000
  • VSCode如何实现AI版本迁移辅助 VSCode跨版本升级的智能建议

    vscode的“ai版本迁移辅助”并非独立功能,而是通过扩展兼容性检查、设置同步、lsp/dap协议支持及社区资源等生态能力协同实现;2. 升级后扩展无法工作时,应检查更新日志、尝试降级或重新安装扩展、禁用冲突扩展、查看控制台错误信息并向作者报告问题;3. 备份设置和扩展列表可通过启用设置同步、手动…

    2026年9月24日
    1000
  • Ubunt16.04 搭建 GPU 显卡驱动 + CUDA9.0 + cuDNN7 详细教程

    Ubunt16.04 搭建 GPU 显卡驱动 + CUDA9.0 + cuDNN7 详细教程Ubunt16.04 搭建 GPU 显卡驱动 + CUDA9.0 + cuDNN7 详细教程Ubunt16.04 搭建 GPU 显卡驱动 + CUDA9.0 + cuDNN7 详细教程Ubunt16.04 搭建 GPU 显卡驱动 + CUDA9.0 + cuDNN7 详细教程

    如果你的电脑运行着 ubuntu16.04,并且配备了一块 nvidia geforce gpu 显卡,那么不利用它来运行深度学习模型就太浪费了!虽然网上关于这方面的教程有很多,但质量参差不齐。本文将详细指导你如何安装 gpu 显卡驱动、cuda9.0 和 cudnn7,助你一步步搭建好环境,值得一…

    2026年9月24日 用户投稿
    600
  • APM开发阅读

    APM开发阅读APM开发阅读APM开发阅读APM开发阅读

    我阅读apm的源码有两个主要目的:一是学习,了解飞控系统和大型项目的组织结构;二是为了移植的需要,满足项目需求。近年来,少儿编程市场非常火热,许多厂商推出了相关的产品,但这些产品大多使用空心杯电机,导致动力不足,且扩展性有限。许多任务需要io或图像识别的支持。 因此,我在考虑使用APM裁剪版的飞控系…

    2026年9月24日 用户投稿
    1600
  • 如何在Linux中切换用户身份?

    Linux中切换用户主要用su和sudo命令;2. su切换用户需密码,su -可加载完整环境;3. sudo允许授权用户以root等身份执行命令而无需对方密码;4. 推荐使用sudo -i或sudo su -切换到root;5. 普通用户需加入sudo组或配置/etc/sudoers文件;6. 编…

    2026年9月24日
    100
  • VSCode的扩展设置是全局的还是局部的?

    VSCode扩展设置默认全局生效,存储于用户配置文件中,但部分扩展如ESLint、Prettier和Python支持项目级局部配置,通过在项目根目录的.vscode/settings.json文件中定义,可覆盖全局设置;在设置界面中,齿轮图标表示可被工作区覆盖,锁图标表示仅限全局修改,用户可根据需求…

    2026年9月24日
    200
  • 如何查找大文件 find命令按大小搜索技巧

    如何查找大文件 find命令按大小搜索技巧如何查找大文件 find命令按大小搜索技巧如何查找大文件 find命令按大小搜索技巧如何查找大文件 find命令按大小搜索技巧

    要在linux中查找大文件,首先使用find命令配合-size参数定位指定大小以上的文件,例如:find /path/to/search -type f -size +5m。其次结合-exec和du、sort等命令可对结果排序并显示详细信息。最后也可用du与sort组合快速列出最大文件,或安装ncd…

    2026年9月24日 用户投稿
    1600
  • 讯维解决KVM鼠标不同步

    讯维解决KVM鼠标不同步讯维解决KVM鼠标不同步讯维解决KVM鼠标不同步讯维解决KVM鼠标不同步

    使用网络kvm时,常遇到本地鼠标与远程界面光标位置不一致的问题,即鼠标不同步现象,严重影响操作流畅性。可通过优化鼠标同步设置、更新驱动程序或选用兼容性更强的设备来有效改善。 1、配置运行Windows 2000操作系统的服务器环境 2、调整鼠标相关参数 3、点击开始菜单,进入控制面板,选择“鼠标”进…

    2026年9月24日 用户投稿
    900
  • 如何监控Linux命令执行时间 time命令性能分析技巧

    如何监控Linux命令执行时间 time命令性能分析技巧如何监控Linux命令执行时间 time命令性能分析技巧如何监控Linux命令执行时间 time命令性能分析技巧如何监控Linux命令执行时间 time命令性能分析技巧

    要查看linux命令执行耗时及分析程序性能,可使用time命令。1. time命令基础用法:在命令前加time,输出包含real(实际时间)、user(用户态时间)、sys(内核态时间),用于初步判断性能瓶颈。2. 精确计时:使用/usr/bin/time获取更详细信息,如内存使用、上下文切换、退出…

    2026年9月24日 用户投稿
    800
  • VSCode 如何自定义编辑器的选中内容动画效果 VSCode 选中内容动画效果的自定义创意方法​

    首先可通过修改settings.json中的workbench.colorcustomizations来自定义选中颜色,1. 添加”editor.selectionbackground”设置背景色,2. 添加”editor.selectionforeground&…

    2026年9月24日
    700
  • 如何分析Linux进程内存 pmap内存映射检查方法

    如何分析Linux进程内存 pmap内存映射检查方法如何分析Linux进程内存 pmap内存映射检查方法如何分析Linux进程内存 pmap内存映射检查方法如何分析Linux进程内存 pmap内存映射检查方法

    要分析linux进程的内存,特别是利用pmap工具,核心操作是获取目标进程pid后执行pmap -x 。1. 获取pid可通过ps aux | grep your_process_name;2. 执行pmap -x 命令查看扩展格式信息,包括address、kbytes、rss、dirty、mode…

    2026年9月24日 用户投稿
    200
  • 如何实现Linux与Windows双系统引导管理?

    答案是先安装Windows再安装Linux,使用GRUB引导;需注意引导模式(UEFI/Legacy)与分区策略(ESP、/、swap、/home),并可通过Live USB修复GRUB。 实现Linux与Windows双系统引导管理,核心在于一个可靠的引导加载器,通常是Linux在安装时提供的GR…

    2026年9月24日
    300
  • VSCode如何优化多项目切换 VSCode工作区快速跳转的实用技巧

    vscode优化多项目切换的核心是使用工作区功能并结合快捷键与插件。1. 创建工作区:通过“文件”→“将工作区另存为…”保存包含多个项目文件夹的.code-workspace文件;2. 配置工作区:在json格式的配置文件中定义folders和settings,如排除node_modules等无关文…

    2026年9月24日
    000
  • Linux中如何安装Git工具_Linux安装Git工具的详细教程

    在Linux系统中安装Git工具是进行版本控制的第一步,尤其对于开发者来说非常关键。不同Linux发行版使用不同的包管理器,因此安装方式略有差异。下面将介绍在主流Linux系统中安装Git的详细步骤。 1. 在Ubuntu/Debian系统中安装Git Ubuntu和Debian系统使用apt作为包…

    2026年9月24日
    100
  • 深入理解 javac 命令中的 ‘当前目录’ 与类路径

    在使用 javac 命令进行 Java 编译时,’当前目录’ 指的是执行该命令时所在的目录,而非源代码文件或 Java 安装路径所在的目录。这对于默认类路径(.)的解析至关重要,影响编译器查找依赖类文件的位置。理解这一概念有助于避免编译错误,并正确配置类路径。 什么是“当前目…

    2026年9月24日
    100
  • 如何监控Linux进程内存泄漏 pmap与valgrind工具使用

    如何监控Linux进程内存泄漏 pmap与valgrind工具使用如何监控Linux进程内存泄漏 pmap与valgrind工具使用如何监控Linux进程内存泄漏 pmap与valgrind工具使用如何监控Linux进程内存泄漏 pmap与valgrind工具使用

    要监控linux进程的内存泄漏,首先使用pmap观察内存增长趋势,再用valgrind定位具体泄漏点。一、使用pmap -x 查看进程内存映射,重点关注anon列和总内存变化,通过定期刷新判断是否存在异常增长;二、利用valgrind –leak-check=full启动程序,分析报告中…

    2026年9月24日 用户投稿
    100

发表回复

登录后才能评论
关注微信