阅读原文:
https://einverne.github.io/post/2017/09/grep.html
https://einverne.github.io/post/2017/11/zgrep-grep-gz-file.html

Linux 下按照正则过滤文本的命令 grep 非常强大,grep 能够把正则匹配的行打印出来。而 zgrep 则能够对压缩包内容进行正则匹配。zgrep 全称是 search compressed files for a regular expression

查看grep的man 介绍第一行,非常简洁精炼 “grep, egrep, fgrep - print lines matching a pattern”,表达了 grep 的作用。

grep 全称是 Global Regular Expression Print。grep 的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容。

grep 可用于 shell 脚本,因为 grep 通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回 0,如果搜索不成功,则返回 1,如果搜索的文件不存在,则返回 2。我们利用这些返回值就可进行一些自动化的文本处理工作。

grep 名字的由来

UNIX 早期的编辑器中,如果要查找比如 junk 这个单词,需要输入 /junk/p 来打印找到的一个行,如果要找所有行,就使用 g/junk/p ,g 是 global search 的意思。

这个功能被独立出来作为了命令,只做一件事情,就是全局搜索,并打印,叫做 grep,其实是 g/regular expression/p 的缩写,可以理解为 g/re/p ,在 vi 或者 sed 中类似的功能也经常能见到。

必须知道的使用方式

grep 的命令格式是

grep [option] pattern files

它的工作方式是,在一个或者多个文件中根据正则搜索匹配内容,将搜索的结果输出到标准输出,不更改源文件内容。

下面这些选项非常常用,记住:

-i 忽略大小写
-v invert match
-n 行号
-B NUM -A NUM
-C NUM

比如说在当前目录下,搜索文件中包含的 password 词

grep password *

grep 会自动在当前目录下搜索并将包含 password 行打印出来,所以千万不要在本地文件中存放密码一类的敏感信息,这一无异于将密码写在显示器上。

忽略大小写匹配

使用 -i 来忽略大小写

grep -i password *

这一行命令会匹配,比如 Password,PASSWORD 等等。

将 grep 作为过滤器来过滤标准输出的内容

cat /etc/passwd | grep 'sshd'

强制让 grep 输出文件名

grep 'sshd' /etc/passwd /dev/null

这时 grep 会打印文件名,冒号,结果

-n 参数会显示行号

grep -n pattern file.txt

显示不包含正则的行

正常情况下 grep 会过滤出匹配 正则的行,使用 -v 参数反之,显示不包含正则的行

grep -v 'junk' *

再比如,如果想要设置 every 但是不想搜索 everyone everybody everywhere 可以使用

grep every * | grep -v one | grep -v body | grep -v where
也可以带-p(perl正则)参数,合并-v参数的各个选项:
grep every * | grep -vP "one|body|where"

显示匹配行前后的行

grep -B 10 -A 20 pattern file.txt

输出匹配 PATTERN 行的前 10 行和 后 20 行。

打印一行中正则匹配的部分

很多时候一行日志中有非常多的内容,我们往往只关心特定的部分,这个时候可以使用 grep 的正则来过滤出我们关心的部分,比如日志中的耗时我们可能会打印出 cost 10ms 这样的内容

grep -o -P "cost [0-9]+ms"
  • -o 表示只输出匹配到的内容,每一行显示一个
  • -P "regex" 表示开启正则过滤
  • 当然如果组合使用 sed 也能够做到同样的事情。

    man参考摘录:

    Matcher Selection
    -E, --extended-regexp
    Interpret PATTERN as an extended regular expression (ERE, see below). (-E is specified by POSIX.)

    -F, --fixed-strings, --fixed-regexp
    Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched. (-F is specified by POSIX,
    --fixed-regexp is an obsoleted alias, please do not use it in new scripts.)

    -G, --basic-regexp
    Interpret PATTERN as a basic regular expression (BRE, see below). This is the default.

    -P, --perl-regexp
    Interpret PATTERN as a Perl regular expression. This is highly experimental and grep -P may warn of unimplemented features.

    在 grep 之上,后人又开发了很多很有用的命令,比如 不解压的情况下搜索压缩包中的内容 ,再比如简便版的 ack-grep

    reference

  • http://www.grymoire.com/Unix/Grep.html#TOC
  • http://stackoverflow.com/a/21412398/1820217
  • zgrep 和 grep 用法类似,不过操作的对象是压缩的内容。支持 bzip2,gzip,lzip, xz 等等。

    zgrep 使用

    但如果想要过滤 Nginx 的 access_log.gz 的压缩文件的内容,如果先解压,然后过滤出有用的文本,再把文件压缩回去,这就变的非常不方便。

    gunzip access_log.gz
    grep "/api" access_log
    gzip access_log

    需要使用三个命令来实现文件的过滤,其实 Linux 下可以使用 zgrep 来一步完成

    zgrep "/api" access_log.gz

    和 grep 类似, zgrep 也可以指定多个文件同时进行搜索过滤

    zgrep "/api" access_log.gz access_log_1.gz

    既然提到了不解压搜索压缩包内容, .gz 的文件可以使用 zgrep ,而对于 .tar.gz 文件

    zcat access.tar.gz | grep -a '/api'
    zgrep -a "/api" access.tar.gz

    其实这些带 z 的命令都包含在 Zutils 这个工具包中,这个工具包还提供了

    zcat  解压文件并将内容输出到标准输出
    zcmp  解压文件并且 byte by byte 比较两个文件
    zdiff 解压文件并且 line by line 比较两个文件
    zgrep 解压文件并且根据正则搜索文件内容
    ztest - Tests integrity of compressed files.
    zupdate - Recompresses files to lzip format.

    这些命令支持 bzip2, gzip, lzip and xz 格式。