阅读原文:
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。我们利用这些返回值就可进行一些自动化的文本处理工作。
在
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
http://www.grymoire.com/Unix/Grep.html#TOC
http://stackoverflow.com/a/21412398/1820217
zgrep 和 grep 用法类似,不过操作的对象是压缩的内容。支持
bzip2,gzip,lzip, xz
等等。
但如果想要过滤 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 格式。