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

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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以后的版本才解决的:

OSBash version^[[:alnum:].-_]+$TEST Result
MacOS(Big Sur 11.4)5.1.4OK
Windows Git Bash4.4.23OK
ubuntu 16.044.3.48FAIL
CentOS 74.2.46FAIL

所以为了避免上面的问题,建议在正则表达式中‘[]’中用到‘-’做普通符号要把它放在最后一个以避免低版本的bash把它当做区间符号。

参考资料


  1. 《3.2.5.2 Conditional Constructs》 ↩︎

以上是关于linux shell:bash 正则表达式判断操作符 =~ 的问题的主要内容,如果未能解决你的问题,请参考以下文章

[Linux Shell学习系列三]常用Shell(Bash)命令-管理文件或目录权限

linux里面bash是啥?

Linux的shell scripts

Shell正则表达式之grepsedawk实操笔记

linux shell:提取正则表达式捕获组(catch group)匹配的字符串

在linux shell(bash)编程中,如何通过递归方式遍历文件