为什么Bash模式匹配?(*[[:class:]])foobar缓慢?

Mar*_*eck 3 regex bash

我有一个文本文件foobar.txt,大约10KB,不是很长.然而,在高性能Linux机器上,以下匹配搜索命令大约需要10秒钟.

bash>shopt -s extglob
bash>[[ `cat foobar.txt` == ?(*[[:print:]])foobar ]]
Run Code Online (Sandbox Code Playgroud)

没有匹配:foobar.txt中的所有字符都是可打印的,但没有字符串"foobar".

搜索应该尝试匹配两个选项,每个选项都不匹配:

"foobar"
Run Code Online (Sandbox Code Playgroud)

这是不稳定的

*[[:print:]]foobar
Run Code Online (Sandbox Code Playgroud)

- 应该是这样的:

应该在一次通过中逐字符扫描文件,每次检查下一个字符是否都是

[[:print:]]foobar
Run Code Online (Sandbox Code Playgroud)

这应该也很快,每个角色都不应该花费毫秒.

事实上,如果我放弃?,就是这样做

bash>[[ `cat foobar.txt` == *[[:print:]]foobar ]]
Run Code Online (Sandbox Code Playgroud)

瞬间的.但这只是上面的第二种选择,没有第一种选择.

那么为什么这么久?

ric*_*ici 6

bash中的glob匹配器没有进行优化.例如,请参阅这个bug-bash线程,在此期间bash维护者Chet Ramey说:

它不是一个正则表达式引擎,它是一个即时解释的匹配器.

由于bash还包含一个正则表达式引擎(使用=~而不是==内部[[ ]]),因此可能没有太多动力去做任何事情.

在我的机器上,等效的regexp(^(.*[[:print:]])?foobar$)在很大程度上受到语言环境的影响[[:print:]]; 由于某种原因,这不会影响glob匹配器.设置LANG = C使正则表达式正常工作.

但是,对于大小的字符串,我会使用grep.