POSIX 系统上 regex.h header 不同实现背后的算法类型
The type of algorithm behind different implementations of the regex.h header on POSIX systems
我最近读了一篇关于正则表达式的精彩文章
(参见 here)这解释了简单性
用于匹配正则表达式的 Thompson NFA 的优雅,
以及其他常规方法的复杂性和缓慢性
表达式。给出的图表显示 Ruby、Python
比汤普森 NFA 长得多,事实上,汤普森
NFA 的匹配时间与众所周知的相似
快速模式匹配 UNIX 程序,例如 grep 和
哇哦。
我的问题是, header(必填
根据 POSIX 标准)musl、glibc 和 uclibc 使用什么算法?
我查看了与 Thompson NFA 进行比较的程序的源代码
到 (GNU/Busybox grep, GNU/Busybox awk) 和 none 的实现
使用 regex.h header,选择他们自己的 in-house 正则表达式匹配 header.
注意:我指的不是符合 POSIX 标准的正则表达式——我指的是 POSIX-compliant(或 UNIX-like)提供的 header系统
称为 regex.h,它提供用于编译和匹配正则表达式的函数和结构。
GNU C 库实现——这是你在 Linux 中使用 <regex.h>
时得到的(以及针对 GNU C 库编译时的任何其他 OS)——在glibc git: posix/regex.h, posix/regex.c, posix/regex_internal.h, posix/regex_internal.c, posix/regcomp.c, and posix/regexec.c. The internal files refer to DFA (deterministic finite automaton), and you can look at the above implementations to see that it indeed implements a DFA. The git history only reaches back to 2002 or so, but the base implementation is older than that; and I'm too lazy to go read old glibc-alpha 邮件列表存档以揭示完整的开发历史细节。 2018 年似乎有一些改进(与 gnulib 正则表达式实现同步时)。
可以这么说,为了执行,甚至 Thompson NFA 都被转换为 DFA,这就是 glibc 用来实现 功能的方法。
uClibc的<regex.h> implementation源于glibc,大致是2002-2006年代,基于git日志(以及源文件中的版权分配)。所以 DFA 也在那里。
uClibc-ng is a fork of uClibc (forked around 2014-2015), and has basically the same <regex.h> implementation 作为 uClibc。
dietlibc uses its own custom (backtracking) implementation, libregex/rx.c,以提供 功能。
musl C library has its own <regex.h> implementation also, based on Ville Laurikari's TRE(近似正则表达式)库。我还没有通过代码对其进行正确分类,但由于它的时间复杂度是线性的。输入字符串(但直到正则表达式的二次方),我相信它也是基于有限自动机的。
Musl 的作者比较了不同 C 库的各种特性,包括简单的正则表达式,here。除其他外,它表明 GNU C 库实现在测试的 C 库中具有最佳的 regcomp()+regexec() 运行时,除 dietlibc 外,其他所有库都具有大致相似的时间行为。
那么,为什么要实现自己的正则表达式功能,而不依赖于标准 C 库提供的功能呢?
我能看到的原因是可移植到 C 库没有正则表达式功能的系统(考虑例如 Windows 上的 GNU grep、sed、awk),并确保正则表达式功能的正确性和效率.
就我个人而言,当我编写 POSIX C 代码(系统编程 – Linux 或 *BSD 中使用的守护程序或实用程序或库)时,我使用 <regex.h>
作为提供由 C 库。如果我要编写一个新的 grep/sed/awk 实用程序,我会将 regex 库合并到源代码中,以便该实用程序可以跨 OSes 移植,包括那些不提供 <regex.h>
作为他们的 C 库的一部分。我相信这就是您看到一些专用实用程序也包含自己的正则表达式库的原因。
我最近读了一篇关于正则表达式的精彩文章 (参见 here)这解释了简单性 用于匹配正则表达式的 Thompson NFA 的优雅, 以及其他常规方法的复杂性和缓慢性 表达式。给出的图表显示 Ruby、Python 比汤普森 NFA 长得多,事实上,汤普森 NFA 的匹配时间与众所周知的相似 快速模式匹配 UNIX 程序,例如 grep 和 哇哦。
我的问题是,
我查看了与 Thompson NFA 进行比较的程序的源代码 到 (GNU/Busybox grep, GNU/Busybox awk) 和 none 的实现 使用 regex.h header,选择他们自己的 in-house 正则表达式匹配 header.
注意:我指的不是符合 POSIX 标准的正则表达式——我指的是 POSIX-compliant(或 UNIX-like)提供的 header系统 称为 regex.h,它提供用于编译和匹配正则表达式的函数和结构。
GNU C 库实现——这是你在 Linux 中使用 <regex.h>
时得到的(以及针对 GNU C 库编译时的任何其他 OS)——在glibc git: posix/regex.h, posix/regex.c, posix/regex_internal.h, posix/regex_internal.c, posix/regcomp.c, and posix/regexec.c. The internal files refer to DFA (deterministic finite automaton), and you can look at the above implementations to see that it indeed implements a DFA. The git history only reaches back to 2002 or so, but the base implementation is older than that; and I'm too lazy to go read old glibc-alpha 邮件列表存档以揭示完整的开发历史细节。 2018 年似乎有一些改进(与 gnulib 正则表达式实现同步时)。
可以这么说,为了执行,甚至 Thompson NFA 都被转换为 DFA,这就是 glibc 用来实现
uClibc的<regex.h> implementation源于glibc,大致是2002-2006年代,基于git日志(以及源文件中的版权分配)。所以 DFA 也在那里。
uClibc-ng is a fork of uClibc (forked around 2014-2015), and has basically the same <regex.h> implementation 作为 uClibc。
dietlibc uses its own custom (backtracking) implementation, libregex/rx.c,以提供
musl C library has its own <regex.h> implementation also, based on Ville Laurikari's TRE(近似正则表达式)库。我还没有通过代码对其进行正确分类,但由于它的时间复杂度是线性的。输入字符串(但直到正则表达式的二次方),我相信它也是基于有限自动机的。
Musl 的作者比较了不同 C 库的各种特性,包括简单的正则表达式,here。除其他外,它表明 GNU C 库实现在测试的 C 库中具有最佳的 regcomp()+regexec() 运行时,除 dietlibc 外,其他所有库都具有大致相似的时间行为。
那么,为什么要实现自己的正则表达式功能,而不依赖于标准 C 库提供的功能呢?
我能看到的原因是可移植到 C 库没有正则表达式功能的系统(考虑例如 Windows 上的 GNU grep、sed、awk),并确保正则表达式功能的正确性和效率.
就我个人而言,当我编写 POSIX C 代码(系统编程 – Linux 或 *BSD 中使用的守护程序或实用程序或库)时,我使用 <regex.h>
作为提供由 C 库。如果我要编写一个新的 grep/sed/awk 实用程序,我会将 regex 库合并到源代码中,以便该实用程序可以跨 OSes 移植,包括那些不提供 <regex.h>
作为他们的 C 库的一部分。我相信这就是您看到一些专用实用程序也包含自己的正则表达式库的原因。