linux shell:bash 正则表达式判断操作符 =~ 的问题

今天完成了一个纯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把它当做区间符号。

参考资料


  1. 《3.2.5.2 Conditional Constructs》 ↩︎

Guess you like

Origin blog.csdn.net/10km/article/details/121723534