在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然後在終端機不停的敲入任意鍵並回車,可以發現,敲入的內容中,除數字外的字元都被原樣的輸出了,而每串數字字元都被替換成? 了。最後敲入 # 後程式退出了。如下:
eruiewdkfj eruiewdkfj 1245 ? fdsaf4578 fdsaf? ... #
- 當在命令列中執行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 1 int numChars = 0, numWords = 0, numLines = 0; %} WORD([^ \t\n\r\a]+) %% \n{ numLines++; numChars++; } {WORD}{ numWords++; numChars += yyleng; return T_WORD; } <<EOF>>{ 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.l gcc -o word-spliter lex.yy.c ./word-spliter < word-spliter.l 输出: WORD: %{ WORD: #define ... WORD: } Chars Words Lines 470 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; } <<EOF>> { 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_H typedef 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: scanner scanner: lex.yy.c token.h gcc -o $@ $< lex.yy.c: scanner.l flex $<
相关推荐:《Linux视频教程》
以上是linux flex是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Linux的5個核心組件分別是內核、Shell、文件系統、系統庫和系統工具。 1.內核管理硬件資源並為應用程序提供服務。 2.Shell作為用戶與系統的接口,解釋並執行命令。 3.文件系統負責數據的存儲和組織。 4.系統庫提供預編譯函數供應用程序調用。 5.系統工具用於系統管理和維護。這些組件協同工作,賦予Linux強大的功能和靈活性。

本文介紹幾種檢查Debian系統OpenSSL配置的方法,助您快速掌握系統安全狀態。一、確認OpenSSL版本首先,驗證OpenSSL是否已安裝及版本信息。在終端輸入以下命令:opensslversion若未安裝,系統將提示錯誤。二、查看配置文件OpenSSL主配置文件通常位於/etc/ssl/openssl.cnf。您可以使用文本編輯器(例如nano)查看:sudonano/etc/ssl/openssl.cnf此文件包含密鑰、證書路徑及加密算法等重要配置信息。三、利用ope

本指南詳細介紹如何在Debian系統上搭建Hadoop開發環境。一、安裝Java開發套件(JDK)首先,安裝OpenJDK:sudoaptupdatesudoaptinstallopenjdk-11-jdk-y配置JAVA_HOME環境變量:sudonano/etc/environment在文件末尾添加(根據實際JDK版本調整路徑):JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"保存並退出,然後執行:source/etc

在Debian系統上有效管理Hadoop資源,需要遵循以下步驟:Hadoop部署:首先,在Debian系統上完成Hadoop的安裝與配置。這包括下載Hadoop發行包、解壓、設置環境變量等必要操作。集群配置:安裝完成後,對Hadoop集群進行配置,涵蓋HDFS(Hadoop分佈式文件系統)和YARN(YetAnotherResourceNegotiator)的設置。需要修改核心配置文件,例如:core-site.xml、hdfs-site.xml、mapred-site.x

提升DebianTomcat日誌安全性,需關注以下關鍵策略:一、權限控制與文件管理:日誌文件權限:默認日誌文件權限(640)限制了訪問,建議修改catalina.sh腳本中的UMASK值(例如,從0027改為0022),或在log4j2配置文件中直接設置filePermissions,以確保合適的讀寫權限。日誌文件位置:Tomcat日誌通常位於/opt/tomcat/logs(或類似路徑),需定期檢查該目錄的權限設置。二、日誌輪轉與格式:日誌輪轉:配置server.xml

Tomcat服務器日誌中的警告信息提示潛在問題,可能影響應用性能或穩定性。有效解讀這些警告信息需要關注以下幾個關鍵點:警告內容:仔細研讀警告信息,明確問題類型、成因及可能的解決方法。警告信息通常會提供詳細描述。日誌級別:Tomcat日誌包含不同級別信息,例如INFO、WARN、ERROR等。 “WARN”級別的警告提示非致命性問題,但需要關注。時間戳:記錄警告發生的時間,以便追溯問題出現的時間點,分析其與特定事件或操作的關係。上下文信息:查看警告信息前後日誌內容,獲取

Tomcat日誌是診斷內存洩漏問題的關鍵。通過分析Tomcat日誌,您可以深入了解內存使用情況和垃圾回收(GC)行為,從而有效定位和解決內存洩漏。以下是如何利用Tomcat日誌排查內存洩漏:1.GC日誌分析首先,啟用詳細的GC日誌記錄。在Tomcat啟動參數中添加以下JVM選項:-XX: PrintGCDetails-XX: PrintGCDateStamps-Xloggc:gc.log這些參數會生成詳細的GC日誌(gc.log),包含GC類型、回收對像大小和時間等信息。分析gc.log

Debian系統下Apache日誌對服務器性能的影響是雙刃劍,既有積極作用,也有潛在的負面影響。積極方面:問題診斷利器:Apache日誌詳細記錄服務器所有請求和響應,是快速定位故障的寶貴資源。通過分析錯誤日誌,可以輕鬆識別配置錯誤、權限問題及其他異常。安全監控哨兵:訪問日誌能夠追踪潛在安全威脅,例如惡意攻擊嘗試。通過設置日誌審計規則,可以有效檢測異常活動。性能分析助手:訪問日誌記錄請求頻率和資源消耗,幫助分析哪些頁面或服務最受歡迎,從而優化資源分配。結合top或htop等


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

記事本++7.3.1
好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3漢化版
中文版,非常好用