网站首页 > 技术文章 正文
前言
grep、sed、awk 是 linux 操作文本的三大利器,合称文本三剑客,它们也是 linux 系统很常用的命令。grep、sed、awk 都支持正则表达式,不过我们中的一些人可能遇到过这样的情况:特定的正则表达式不适用于某些 Linux 命令。例如,正则表达式 \d 在 sed 和 awk 不支持,grep 命令不使用 -P 参数同样也是不支持。但是,相同的正则表达式适用于 Java 或 Python。这可能会让我们感到困惑。下面,我们看下此类问题并解释为什么会发生这种情况。
问题描述
我们创建一个测试文本 a.txt 做实验,a.txt内容如下:
[root@z2024 tmp]# cat a.txt
Hello,Can you see me?
127.0.0.1 example.com
dddwww
0123456789
abcdefg
正则表达式 [0-9] 是匹配一个数字。我们使用 [0-9]测试下grep、sed、awk命令是否可以支持:
[root@z2024 tmp]# grep '[0-9]' a.txt
127.0.0.1 example.com
0123456789
[root@z2024 tmp]# sed -n '/[0-9]/p' a.txt
127.0.0.1 example.com
0123456789
[root@z2024 tmp]# awk '/[0-9]/' a.txt
127.0.0.1 example.com
0123456789
[root@z2024 tmp]#
看起来没问题
在正则表达式中 \d 是 [0-9] 的缩写形式,我们使用 \d看这三命令是否可以支持:
[root@z2024 tmp]# grep '\d' a.txt
dddwww
abcdefg
[root@z2024 tmp]# grep -E '\d' a.txt
dddwww
abcdefg
[root@z2024 tmp]# grep -P '\d' a.txt
127.0.0.1 example.com
0123456789
[root@z2024 tmp]# sed -n '/\d/p' a.txt
dddwww
abcdefg
[root@z2024 tmp]# sed -nr '/\d/p' a.txt
dddwww
abcdefg
[root@z2024 tmp]# awk '/\d/' a.txt
dddwww
abcdefg
[root@z2024 tmp]#
从上面可以看得到,只有 grep加上 -P参数才是对的。
解释上面这个现象,可以看下 man grep
grep understands three different versions of regular expression syntax: “basic” (BRE), “extended” (ERE) and “perl” (PCRE). In GNU grep there is no difference in available functionality between basic and extended syntaxes. In other implementations, basic regular expressions are less powerful. The following description applies to extended regular expressions; differences for basic regular expressions are summarized afterwards. Perl-compatible regular expressions give additional functionality, and are documented in pcresyntax(3) and pcrepattern(3), but work only if PCRE is available in the system.
grep 支持三种不同版本的正则表达式, 默认是 BRE。那 BRE、ERE、PCRE 有什么区别呢?
-E, --extended-regexp
Interpret PATTERN as an extended regular expression (ERE, see below).
-G, --basic-regexp
Interpret PATTERN as a basic regular expression (BRE, see below). This is the default.
-P, --perl-regexp
Interpret the pattern as a Perl-compatible regular expression (PCRE). This is experimental and grep -P may warn of unimplemented features.
BRE, ERE, and PCRE
- BRE – Basic Regular Expressions
- ERE – Extended Regular Expressions
- PCRE – Perl Compatible Regular Expressions
正则表达式的 POSIX 规范,分为基本型正则表达式(Basic Regular Expression,BRE)和扩展型正则表达式(Extended Regular Expression,ERE)两大流派。再后来出现了 Perl 的正则表达式,它已经演化成了 PCRE(Perl Compatible Regular Expressions)。PCRE 已经成为一种事实上的标准,它拥有一组丰富而强大的原子表达式。PCRE 没有“基本”或“扩展”级别。
BRE 是最古老的正则表达式语法。顾名思义,它只支持非常基本的功能。例如,标准 POSIX BRE 不支持很多你知道的正则表达式功能,如前面说的 \d,还有 \s , | , ? ,+ 等等。另外,BRE 要求将元字符 ( ) ,{ } 进行转义 \(\),\{\} ,而扩展正则表达式 (ERE)则不用。
PCRE 的语法比 BRE 和 ERE 更强大、更灵活。下面看一下仅在 PCRE 中可用的一些功能:
- Look-around - 前后查找
- 非贪婪匹配 - *?、+?、{m, }?
- 区分大小写/不区分大小写的匹配 - (?i) 和 (?-i)
- 用于匹配数字,非数字字符等的简写 - \d、\D 等
grep、vi、sed 都属于 BRE,sed 使用 -r 参数就可以切换成 ERE,egrep、awk 则属于 ERE。所以 grep 使用 PCRE 正则表达式 -P 参数才可以支持 \d。
Grep on Linux and Mac
在 Mac 上 的 grep 命令没有 -P 这个选项(我较新的 Mac 系统 sonama 也没有),查看 grep version 原来它是 BSD grep,linux 上系统的 grep 是属于 GNU grep。BSD 版本使用 POSIX 兼容正则表达式,GNU 版本使用 PCRE 。
$ grep -V
grep (BSD grep, GNU compatible) 2.6.0-FreeBSD
当然你也可以通过 HomeBrew 自行安装 GNU grep,吐槽下苹果这么牛逼的命令行工具也不更新下。
总结
不同的工具可能使用不同版本的正则表达式,大家使用的时候可以看下它的文档或者查阅相关资料,对于 sed 和 awk 无法使用 PCRE ,懂 perl 的同学也可以使用它来替代。如果您在阅读过程中发现了任何问题,或者有任何可以改进的地方,欢迎留言或者私信我。
参考链接:
https://en.wikipedia.org/wiki/Regular_expression
https://en.wikibooks.org/wiki/Regular_Expressions/POSIX_Basic_Regular_Expressions
https://www.baeldung.com/linux/digit-pattern-not-supported-by-grep-regex
https://xebia.com/blog/learning-grep/
猜你喜欢
- 2024-09-10 oracle实用sql分享:杀进程、长时间操作等等
- 2024-09-10 走在前沿的弄潮儿,怎能不会Git的那些奇技淫巧
- 2024-09-10 TCP“三次握手,四次挥手”你真的懂吗?
- 2024-09-10 制作 deb 软件包(如何制作deb包)
- 2024-09-10 详解虚拟化之KVM概念、架构、功能、常用工具及部署
- 2024-09-10 Linux find命令一定要知道这些(linux find命令的使用)
- 2024-09-10 inux 文本处理三剑客--grep/sed/awk
- 2024-09-10 db2入门必看命令清单--日常运维必需
- 2024-09-10 浅谈Linux中的&&和ll(linux中atime)
- 2024-09-10 浅谈Linux中的&&和ll,补充&和l
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)