Fluent Bit 内置 Onigmo 正则引擎语法特性、构建方式与底层集成原理【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit导读OnigmoOniguruma-mod是一个从 Oniguruma 分支出来的正则表达式库重点支持 Perl 5.10 引入的\K、\R、(?(cond)yes|no)等新语法并从 Ruby 2.x 反向移植了大量补丁它自 Ruby 2.0 起便是 Ruby 的默认正则库。在 Fluent Bit 项目中Onigmo 被直接内置在 lib/onigmo 目录下作为解析器Parser、过滤器与 Record Accessor 底层统一使用的正则引擎默认语法ONIG_SYNTAX_RUBYUTF-8 编码。读完本文你将掌握 Onigmo 的完整语法手册、三种平台下的构建安装方法、C API 使用要点以及它在 Fluent Bit 内部从flb_regex_*封装到Regex解析器、测试用例的完整调用链。一、Onigmo 是什么与 Oniguruma 的关系Onigmo 的定位在其 README.md 中写得很明确它是Oniguruma 的正则库分支专注于支持 Perl 5.10 的新表达式例如\K保留keep一种更简洁的 look-behind 表达\R换行符linebreak(?(cond)yes|no)条件表达式。同时由于 Onigmo 是 Ruby 2.0 及以后版本的默认正则库其代码中沉淀了大量从 Ruby 2.x 反向移植的补丁因此它的行为与 Ruby 的 Regexp 高度一致。这对 Fluent Bit 用户有一个直接好处在配置 Parser、Filter如 grep、record_modifier、rewrite_tag时编写的正则语法与 Ruby 生态的规则基本对齐降低了跨语言迁移成本。在 Fluent Bit 中的角色从源码结构看Fluent Bit 将 Onigmo 作为内置第三方库托管在 lib/onigmo核心封装位于 src/flb_regex.c接口声明见 include/fluent-bit/flb_regex.h。该文件直接#include onigmo.h并通过onig_init()/onig_new()/onig_search()/onig_foreach_name()等 API 提供上层能力#include onigmo.h编译时指定ONIG_ENCODING_UTF8与ONIG_SYNTAX_RUBY见 src/flb_regex.c这意味着 Fluent Bit 中所有经flb_regex_create编译的模式默认走 Ruby 语法 UTF-8 编码。二、获取与构建安装Case 1Unix 与 Cygwin 平台Autotools标准流程如下./autogen.sh # 若 configure 不存在 ./configure make make install配套操作make test # 运行测试 make uninstall # 卸载安装后可用onigmo-config检查编译配置onigmo-config --cflags onigmo-config --libs onigmo-config --prefix onigmo-config --exec-prefixCase 2WindowsVisual C执行build_nmake.cmd对应仓库根目录的 lib/onigmo/build_nmake.cmdbuild_x64或build_x86将作为工作/输出目录产物为文件说明onigmo_s.lib静态链接库onigmo.lib动态链接导入库onigmo.dll动态链接库运行测试覆盖 ASCII / Shift_JIS / EUC-JP / Unicodebuild_nmake.cmd test注意运行测试需要与 Onigmo 同位数bitness的 Python。Case 3WindowsMinGW / MSYS2mingw32-make -f win32/Makefile.mingw输出目录为build_x86-64、build_i686等产物为libonigmo.a静态库、libonigmo.dll.a导入库与onigmo.dll。测试命令为mingw32-make -f win32/Makefile.mingw test若在 MSYS2 中使用 MinGW也可以像 Unix 一样直接./configure make此时 DLL 名称会带 API 版本号例如libonigmo-6.dll。此外仓库还提供基于 CMake 的构建支持lib/onigmo/CMakeLists.txtFluent Bit 正是通过自身的 lib/CMakeLists.txt 体系将 onigmo 作为子库编译集成。三、正则语法完整手册源自 lib/onigmo/doc/RE默认语法为ONIG_SYNTAX_RUBY。以下内容完整继承自官方语法文档是编写 Fluent Bit Parser 正则时的权威参考。3.1 基本语法元素元素含义\转义启用或禁用元字符\|交替alternation(...)分组[...]字符类3.2 字符与转义写法含义码点/值\t水平制表符0x09\v垂直制表符0x0B\n换行0x0A\r回车0x0D\b退格仅字符类内有效0x08\f换页0x0C\a响铃0x07\e转义0x1B\nnn八进制字符按编码字节值—\xHH十六进制字符按编码字节值—\x{7HHHHHHH}宽十六进制字符码点值—\uHHHH宽十六进制字符码点值—\cx/\C-x控制字符—\M-x元字符x|0x80—\M-\C-x元控制字符—补充在ONIG_SYNTAX_PERL下还可使用\o{nnn}八进制字符。3.3 字符类型Character Types.任意字符默认不含换行\w/\W单词字符 / 非单词字符。非 Unicode 下为字母数字加_Unicode 下为General_Category -- (Letter|Mark|Number|Connector_Punctuation)\s/\S空白 / 非空白。非 Unicode 下为\t \n \v \f \r \x20Unicode 下还包括 0x0085(NEL) 与 Line/Paragraph/Space Separator 类\d/\D十进制数字 / 非数字Unicode 下对应Decimal_Number\h/\H十六进制数字[0-9a-fA-F]/ 非十六进制数字。以上类型是否匹配非 ASCII 字符取决于ONIG_OPTION_ASCII_RANGE选项。字符属性Character Property\p{property-name}\p{^property-name}取反\P{property-name}取反属性名分三档所有编码均可用Alnum, Alpha, Blank, Cntrl, Digit, Graph, Lower, Print, Punct, Space, Upper, XDigit, Word, ASCIIEUC-JP、Shift_JIS、CP932 下额外可用Hiragana, Katakana, Han, Latin, Greek, CyrillicUTF-8/UTF-16/UTF-32 下可使用完整的 Unicode 属性参见UnicodeProps.txt。细节差异\p{Punct}在非 Unicode 编码下会匹配$^|~这九个字符与[[:punct:]]一致但在 Unicode 编码下不匹配它们Unicode 下可用\p{XPosixPunct} 匹配这九个字符。换行与字素簇\RLinebreakUnicode 下等价于(?\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}])非 Unicode 下等价于(?\x0D\x0A|[\x0A-\x0D])\XExtended Grapheme clusterUnicode 下遵循 UAX #29 文本分段规则非 Unicode 下等价于(?\x0D\x0A|(?m:.))。3.4 量词Quantifier贪婪greedy?、*、、{n,m}、{n,}、{,n}等价{0,n}、{n}。懒惰reluctant??、*?、?、{n,m}?、{n,}?、{,n}?。占有possessive贪婪且匹配后不回溯?、*、。其中{n,m}、{n,}、{n}仅在ONIG_SYNTAX_JAVA与ONIG_SYNTAX_PERL下为占有语义。例如/a*/等价于/(?a*)/。3.5 锚点Anchors锚点含义^行首$行尾\b/\B词边界 / 非词边界\A字符串开头\Z字符串结尾或结尾前的新行之前\z字符串结尾\G当前搜索尝试开始处3.6 字符类Character Class^...否定类优先级最低x-y范围[...]集合字符类内嵌套字符类....交集低优先级仅高于^。示例[a-w[^c-g]z]等价于([a-w] AND ([^c-g] OR z))结果为[abh-w]。若想把[、-、]当作普通字符需要用\转义。POSIX 括号[:xxxxx:]否定用[:^xxxxx:]非 Unicode 下alnum, alpha, ascii, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit, wordUnicode 下各类型映射到对应 General_Category 集合如digit对应Decimal_Numberword对应Letter|Mark|Decimal_Number|Connector_Punctuation等。POSIX 括号是否匹配非 ASCII 字符取决于ONIG_OPTION_ASCII_RANGE与ONIG_OPTION_POSIX_BRACKET_ALL_RANGE两个选项。3.7 扩展组Extended Groups(?#...)注释(?imxdau-imx)选项开关。i忽略大小写m多行.也匹配换行x扩展模式。字符集选项d默认\w \d \s不匹配非 ASCIIaASCII开启ONIG_OPTION_ASCII_RANGEuUnicode关闭ONIG_OPTION_ASCII_RANGE(?imxdau-imx:subexp)对子表达式生效的选项(?:subexp)非捕获组(subexp)捕获组(?subexp)前瞻、(?!subexp)负向前瞻、(?subexp)后顾、(?!subexp)负向后顾。后顾子表达式必须是定宽的顶层交替可以不同长度如(?a|bc)合法(?aaa(?:b|cd))不合法负向后顾内不允许捕获组但允许(?:)\K保留等价于一种 look-behind 表达——\K左侧匹配的内容不包含在结果中(?subexp)原子组组内不回溯(?namesubexp)/(?namesubexp)命名组组名每个字符须为单词字符命名组同时拥有编号同一名字可赋给多个子表达式(?(cond)yes-subexp)/(?(cond)yes-subexp|no-subexp)条件表达式。(cond)可为(n)检查编号捕获组是否已匹配、(name)/(name)检查命名组是否已匹配。文档同时标注了一个已知 BUG若名字被定义多次只检查最左的组而按语义应与\kname一致(?~subexp)absence operator实验性匹配不包含任何与 subexp 匹配的字符串的补集形式上类似(?:(?!subexp).)*但更易书写。例如(?~abc)匹配、ab、ccdd等不匹配abc、aabc\/\*(?~\*\/)\*\/可匹配 C 风格注释(?~)永不匹配。3.8 反向引用Backreferences\n、\kn、\knn≥1引用第 n 组\k-n、\k-n从引用位置向前倒数的第 n 组\kname、\kname按名字引用。同名多组时优先检查最后匹配的组依次向前若定义了命名组且未设置ONIG_OPTION_CAPTURE_GROUP禁止按编号反向引用ONIG_SYNTAX_PERL下支持\g{n}、\g{-n}、\g{name}且同名时只检查最左组。带递归层级recursion level的反向引用\knlevel、\kn-level、\k-nlevel、\k-n-level、\knamelevel、\kname-level引用相对于引用位置的递归层级的组。文档示例/\A(?a|.|(?:(?b.)\ga\kb))\z/.match(reee) /\A(?a|.|(?:(?b.)\ga\kb0))\z/.match(reer)以及用\kname1校验 XML 风格嵌套标签的完整示例(?etag / \kname1 ){0}。3.9 子表达式调用Subexp Calls\g0/\g0递归调用整个模式\gn/\gnn≥1调用第 n 组\g-n从调用位置向前倒数第 n 组\gn向后数第 n 组\gname/\gname按名调用。限制不允许最左递归调用例如(?namea|\gnameb)报错而(?namea|b\gnamec)合法Ruby 语法下不允许对同名多组进行调用。ONIG_SYNTAX_PERL下改用(?name)、(?n)、(?-n)、(?n)、(?R)、(?0)且允许同名多组调用取最左子表达式。3.10 捕获组行为Captured Group无名组(...)的捕获行为随上下文变化命名组不受影响场景行为case 1未使用命名组、无选项(...)作为捕获组case 2/.../gONIG_OPTION_DONT_CAPTURE_GROUP(...)视为非捕获组(?:...)case 3使用了命名组、无选项(...)视为非捕获组禁止编号引用/调用case 4/.../GONIG_OPTION_CAPTURE_GROUP(...)作为捕获组允许编号引用/调用3.11 语法相关选项与差异附录 A语法相关选项ONIG_SYNTAX_RUBY(?m)使.也匹配换行ONIG_SYNTAX_PERL/JAVA/PYTHON(?s)使.匹配换行(?m)使^匹配换行后、$匹配换行前ONIG_SYNTAX_PERL(?d)、(?l)等价于(?u)。Onigmo 原创扩展\h/\H十六进制数字类型、命名组(?name...)/(?name...)、命名反向引用\kname、子表达式调用\gname/\ggroup-num。相对 Perl 5.18.0 缺失的特性\N{name}、\N{Uxxxx}、\N、\l \u \L \U \C、\v \V \h \H注意与 Onigmo 自身\h语义不同、(?{code})、(??{code})、(?|...)、(?[])、(*VERB:ARG)\Q...\E仅在 Perl/Java 语法下有效。与 Ruby 1.8 的 Japanized GNU regex(0.12) 相比的差异新增字符属性、\h \H、后顾、占有量词、字符类内集合与交集操作、命名组与子表达式调用、多字节编码下字符类内可识别八进制/十六进制序列如[\xa1\xa2]、孤立选项作用范围到下一个)、允许不成对左花括号作为普通字符、支持否定 POSIX 括号[:^xxxx:]、新增[:ascii:]、不允许前瞻重复如/(?a)*/报错、忽略大小写对转义序列生效/\x61/i ~ A、范围量词最小值可省略/a{,n}/但不可同时省略、/{n}?/不是懒惰量词、非法反向引用报错、零宽匹配死循环的停止规则等。默认语法下禁用的特性捕获历史(?...)与(?name...)示例/(?a)*/.match(aaa)可参考 lib/onigmo/sample/listcap.c。已知问题ProblemsOnigmo 不校验非法编码字节序列——例如 UTF-8 下/./u ~ \xa3会把无效首字节当作字符/\w/ ~ a\xf3\x8ec不检查不完整字节序列。在 Fluent Bit 处理脏数据日志时这一行为值得留意。四、C API 使用要点源自 lib/onigmo/doc/API 与 README.md4.1 包含头文件#include onigmo.h两个可选的命名冲突逃生口若想禁用 onigmo.h 中的UChar即unsigned char类型定义先定义ONIG_ESCAPE_UCHAR_COLLISION再包含头文件若想禁用regex_t类型定义先定义ONIG_ESCAPE_REGEX_T_COLLISION再包含头文件。4.2 编译与链接Unix/Cygwin 下默认 prefix 为/usr/localcc sample.c -L/usr/local/lib -lonigmoWindows 下若使用静态链接库onigmo_s.lib需给编译器加选项-DONIG_EXTERNextern。4.3 核心 API 速览结合 src/flb_regex.c阶段调用说明初始化onig_init()/onig_end()全局初始化/收尾对应 Fluent Bit 的flb_regex_init/flb_regex_exit编译onig_new(reg, pattern, pattern_end, option, enc, syntax, einfo)返回ONIG_NORMAL表示成功Fluent Bit 固定传ONIG_ENCODING_UTF8ONIG_SYNTAX_RUBY搜索onig_search(reg, str, end, start, range, region, ONIG_OPTION_NONE)ONIG_MISMATCH表示未命中返回其他负值为错误区域onig_region_new()/onig_region_free(region, 1)保存捕获组起止位置region-beg[i]/region-end[i]命名遍历onig_foreach_name(reg, cb, data)逐个回调命名组Fluent Bit 用它实现键值抽取见cb_onig_named释放onig_free(reg)释放已编译模式Fluent Bit 还额外解析了/pattern/option形式在 src/flb_regex.c 的check_option中模式尾部mONIG_OPTION_MULTILINE、iONIG_OPTION_IGNORECASE、xONIG_OPTION_EXTEND会被转换成对应选项o不被支持并输出调试日志未知选项回退为默认选项。4.4 示例程序一览文件说明lib/onigmo/sample/simple.c最小 Onigmo API 示例lib/onigmo/sample/names.c命名组回调示例lib/onigmo/sample/encode.c多编码示例lib/onigmo/sample/listcap.c捕获历史示例lib/onigmo/sample/posix.cPOSIX API 示例lib/onigmo/sample/sql.c可变元字符示例lib/onigmo/sample/syntax.cPerl / Java / ASIS 语法测试lib/onigmo/sample/crnl.cCRNL 测试4.5 三套 API 并存Onigmo 同时提供 Onigmo APIonigmo.h、GNU regex APIlib/onigmo/onigmognu.h lib/onigmo/reggnu.c与 POSIX APIlib/onigmo/onigmoposix.h lib/onigmo/regposix.c lib/onigmo/regposerr.c分别满足不同调用风格。五、源码文件地图lib/onigmo/README.md 官方清单文件职责lib/onigmo/onigmo.hOnigmo API 公共头文件lib/onigmo/onigmo-config.in配置检查程序模板lib/onigmo/onigmo.pyOnigmo 的 Python 模块lib/onigmo/regenc.h字符编码框架头文件lib/onigmo/regint.h / lib/onigmo/regparse.h内部定义lib/onigmo/regcomp.c编译与优化函数lib/onigmo/regenc.c字符编码框架lib/onigmo/regerror.c错误信息函数lib/onigmo/regext.c扩展 APIdeluxe 版 APIlib/onigmo/regexec.c搜索与匹配函数lib/onigmo/regparse.c解析函数lib/onigmo/regsyntax.c语法函数与内置语法定义lib/onigmo/regtrav.c捕获历史树遍历lib/onigmo/regversion.c版本信息函数lib/onigmo/st.h / lib/onigmo/st.c哈希表函数lib/onigmo/onigmognu.h / lib/onigmo/reggnu.cGNU regex APIlib/onigmo/onigmoposix.h / lib/onigmo/regposix.c / lib/onigmo/regposerr.cPOSIX APIlib/onigmo/enc/各编码实现ASCII、JIS、EUC-JP/TW/KR、Shift_JIS、Windows-31J、Big5、GB18030/GBK、KOI8-R/U、ISO-8859 系列、UTF-8/16/32、Windows-125x、CP949、Emacs 内部编码、GB2312、US-ASCII 等lib/onigmo/win32/Makefile / lib/onigmo/win32/Makefile.mingw / lib/onigmo/win32/config.h / lib/onigmo/win32/onigmo.rcWindows 构建支持Unicode 的 case folding 数据与属性数据位于 lib/onigmo/enc/unicode/。字符类型表生成器为 lib/onigmo/enc/mktable.c。六、在 Fluent Bit 中的集成与实测验证6.1 封装层flb_regexinclude/fluent-bit/flb_regex.h 暴露了如下核心接口flb_regex_create(pattern)编译模式内部走str_to_regex→onig_newflb_regex_do(regex, str, slen, result)搜索并返回捕获组数量region-num_regs - 1ONIG_MISMATCH返回 -1flb_regex_match(regex, str, slen)纯布尔匹配0/1/负值错误flb_regex_parse(regex, result, cb_match, data)基于onig_foreach_name遍历命名组把name与valueregion-beg/end切片交给回调返回最后匹配位置flb_regex_results_get / flb_regex_results_size / flb_regex_results_release捕获结果访问与释放flb_regex_destroy/flb_regex_exit释放与全局收尾。6.2 上层消费者Regex 解析器src/flb_parser_regex.c 是典型消费者第 132 行用flb_regex_do做首次搜索第 154 行用flb_regex_parse把命名组按名提取为键值对cb_results回调从而把一条原始日志按正则切成结构化字段。这就是conf/parsers.conf中Regex类型 Parser 的底层执行路径。Fluent Bit 的 Parser、Filtergrep/record_modifier/rewrite_tag 等与 Record Accessor 均复用这套封装保证正则行为全局一致。6.3 测试佐证单元测试 tests/internal/regex.c 验证了完整链路例如模式/(?str[a-z]) (?num\d) (?time\d{4}\/\d{2}\/\d{2})/对输入string 1234 2022/10/24的抽取期望得到strstring、num1234、time2022/10/24三个键值对。测试同时覆盖了命名组回调、结果索引flb_regex_results_get、结果数量flb_regex_results_size等 API。此外 tests/internal/fuzzers/utils_fuzzer.c 也调用了正则接口用于健壮性模糊测试。6.4 在 Fluent Bit 配置中的典型用法结合上述解析器实现Fluent Bit 配置文件中的 Regex Parser 通常写作示例位于 conf/parsers.conf 同族结构[PARSER] Name my_regex_parser Format regex Regex ^(?time\d{4}/\d{2}/\d{2}) (?level[A-Z]) (?msg.*)$ Time_Key time Time_Format %Y/%m/%d其中Regex字段直接使用上文第三节的 Ruby 语法默认ONIG_SYNTAX_RUBY UTF-8命名组(?name...)即成为输出的记录字段名/pattern/i、/pattern/m、/pattern/x形式可追加选项对应check_option解析出的ONIG_OPTION_IGNORECASE、ONIG_OPTION_MULTILINE、ONIG_OPTION_EXTEND。七、总结Onigmo 作为 Fluent Bit 内置的正则引擎为其提供了贴近 Ruby/Perl 的现代正则语法\K、\R、条件组、命名组、子表达式调用、absence operator 等与多编码支持。理解 lib/onigmo/doc/RE 的语法手册、lib/onigmo/README.md 的构建与 API 说明再对照 src/flb_regex.c、src/flb_parser_regex.c 与 tests/internal/regex.c 的实现与测试你就能在 Fluent Bit 的 Parser/Filter 配置中准确编写、调试并预测正则行为——同时也能把 Onigmo 作为独立库快速集成进自己的 C 项目。【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考