今天完成了一个纯shell脚本的小项目,里面用到了大量的正则表达式判断,就是利用shell 的 =~ 操作符判断字符串是否匹配指定的正则表达式以验证用户输入的有效性。
关于bash正则表达式的条件判断操作符=~,gnu官方网站上《Bash Reference Manual(Bash参考手册)》有详细说明 1
差不多就是这样子,使用很方便
$ [[ "hello world" =~ wor(ld)? ]] && echo matched
matched
开发这个小项目时我在macOS和windows/MSYS下都测试通过了,以为大功告成的时候,拿到ubuntu下一跑,居然通不过。
如此简单的一个正则表达式判断居然不能匹配
$ [[ 'unknow_author' =~ ^[[:alnum:].-_]+$ ]] && echo matched
上面的代码在macOS和Windows/MSYS下都会输出‘matched’,表示字符串unknow_author匹配正则表达式[[:alnum:].-_]+$
但在ubuntu 16.04,和 CentOS 7下都不能正确输出,百思不得其解。
只好再翻《Bash Reference Manual》的原文,在3.2.5.2 Conditional Constructs章节找到
下面这段的说明,意思就是如果=~ 右边的正则表达语法不正确,则[[ expression ]] 表达式会返回2

赶紧到ubuntu下验证,如下图果然返回2,

也就是说bash认为^[[:alnum:].-_]+$这个正则表达式有语法错误,可是何错之有啊?难道不识别[:alnum:]?,换成^[a-zA-Z0-9.-_]+$也还是不行。
只好把目光聚焦到后半段.-_,这里原本代表三个字符,会不会bash把这个-当做表示区间的符号(类型0-9中的-)?我果断修改它们的顺序,改为._-,再次测试,通过!

同样是bash,为什么macOS和 Windows/MSYS 下就没问题呢?我检查了几个平台的bash版本,做成下表格,一目了然,不用怀疑这是bash的bug,至少在4.4.38以后的版本才解决的:
| OS | Bash version | ^[[:alnum:].-_]+$TEST Result |
|---|---|---|
| MacOS(Big Sur 11.4) | 5.1.4 | OK |
| Windows Git Bash | 4.4.23 | OK |
| ubuntu 16.04 | 4.3.48 | FAIL |
| CentOS 7 | 4.2.46 | FAIL |
所以为了避免上面的问题,建议在正则表达式中‘[]’中用到‘-’做普通符号要把它放在最后一个以避免低版本的bash把它当做区间符号。
Shell脚本中的正则怪异:跨平台正则表达式解析差异

作者分享了在不同操作系统中使用bash shell脚本进行正则表达式判断时遇到的问题,发现版本差异导致的语法解析问题,特别是关于特殊字符'-'的处理。通过实例和版本对比揭示了这一bug,并给出了解决方案。
452

被折叠的 条评论
为什么被折叠?



