记 grep命令在Ubuntu上使用失败的问题
问题/任务
我有一个任务,要用shell命令从文本文件中提取ip地址,文本文件内容就像这样:
185.155.192.77 - - [17/Jul/2023:02:27:22 +0000] "GET / HTTP/1.1" 404 1234
我想到可以用grep 来实现,找到一个ip地址的正则表达式,用来提取ip正好,命令行是这样:
grep -E -o '\b(?:\d{1,3}.){3}\d{1,3}\b' access.log
在mac 上 执行的很成功,但是当我在Ubuntu执行时,grep没有返回任何结果,到底是什么环节出了问题?
解决过程
请教chatgpt,gpt给出了几个可能的原因,前2个分别是:正则语法错误/版本兼容问题,Ubuntu 上的grep使用基本的正则表达式,如要使用Perl 兼容的正则,需要加 -P
grep -P -o '\b(?:\d{1,3}.){3}\d{1,3}\b' access.log
问题完美解决。那么2个环境的grep 有什么不同呢?
在mac上,grep --version
grep (BSD grep, GNU compatible) 2.6.0-FreeBSD
在Ubuntu上,grep --version
grep (GNU grep) 3.4
两者版本差别还是挺大的,看来写Shell 脚本需要特别处理这种兼容性问题!
后来
什么是Perl兼容的正则表达式?来自gpt的回答是这样:
Perl兼容的正则表达式是一种正则表达式的语法,它与Perl编程语言中使用的正则表达式语法兼容。Perl正则表达式在文本处理和模式匹配中非常强大和灵活,因此被广泛用于许多编程语言和工具中,不仅限于Perl自身。
Perl兼容的正则表达式通常支持以下功能:
- 元字符:像
.
、*
、+
、?
等常见的元字符用于匹配字符和重复。
2. 字符类:使用[]
来指定一个字符集合,如[a-zA-Z]
表示匹配任何大小写字母。
3. 锚点:使用^
(开始)和$
(结束)来匹配文本的开头和结尾。
4. 分组:使用()
来创建捕获组,可以在匹配后引用它们。
5. 量词:使用{}
来指定重复次数,如{1,3}
表示重复1到3次。
6. 转义字符:使用\
来转义特殊字符,以便匹配它们本身。
7. 或运算:使用|
来表示逻辑或,例如cat|dog
表示匹配"cat"或"dog"。
8. 后向引用:捕获组可以在模式中后向引用,允许你匹配先前捕获的文本。
9. 零宽断言:使用特殊的断言如(?=...)
(正向先行断言)和(?!...)
(负向先行断言)来查找特定条件而不消耗输入。
10. 修饰符:使用修饰符(如i
表示不区分大小写,m
表示多行模式)来调整匹配行为。
因为Perl正则表达式语法非常强大,所以它在文本处理和模式匹配任务中非常有用,被许多编程语言和工具所采纳和实现,包括Python、Java、JavaScript等。它是一个功能丰富的工具,可以用于字符串匹配、文本解析、数据提取等各种任务。如果你要在特定的编程语言中使用Perl兼容的正则表达式,你需要查看该语言的文档,以了解如何使用和实现这些正则表达式。因为Perl正则表达式语法非常强大,所以它在文本处理和模式匹配任务中非常有用,被许多编程语言和工具所采纳和实现,包括Python、Java、JavaScript等。它是一个功能丰富的工具,可以用于字符串匹配、文本解析、数据提取等各种任务。如果你要在特定的编程语言中使用Perl兼容的正则表达式,你需要查看该语言的文档,以了解如何使用和实现这些正则表达式。