记 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兼容的正则表达式通常支持以下功能:

  1. 元字符:像.*+? 等常见的元字符用于匹配字符和重复。
    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兼容的正则表达式,你需要查看该语言的文档,以了解如何使用和实现这些正则表达式。

posted @ 2023-11-08 12:15  ahguo  阅读(100)  评论(0编辑  收藏  举报