Grep
grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。Unix的grep家族包括grep、egrep和fgrep。egrep和fgrep的命令只跟grep有很小不同。egrep是grep的扩展,支持更多的re元字符, fgrep就是fixed grep或fast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示回其自身的字面意义,不再特殊。Linux使用GNU版本的grep。它功能更强,可以通过-G、-E、-F命令行选项来使用egrep和fgrep的功能。
grep的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到屏幕,不影响原文件内容。
grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。
语法
grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][--help][范本样式][文件或目录...]
匹配模式选择: -E, --extended-regexp 扩展正则表达式egrep -F, --fixed-strings 一个换行符分隔的字符串的集合fgrep -G, --basic-regexp 基本正则 -P, --perl-regexp 调用的perl正则 -e, --regexp=PATTERN 后面根正则模式,默认无 -f, --file=FILE 从文件中获得匹配模式 -i, --ignore-case 不区分大小写 -w, --word-regexp 匹配整个单词 -x, --line-regexp 匹配整行 -z, --null-data 一个 0 字节的数据行,但不是空行 杂项: -s, --no-messages 不显示错误信息 -v, --invert-match 显示不匹配的行 -V, --version 显示版本号 --help 显示帮助信息 --mmap use memory-mapped input if possible 输入控制: -m, --max-count=NUM 匹配的最大数 -b, --byte-offset 打印匹配行前面打印该行所在的块号码。 -n, --line-number 显示的加上匹配所在的行号 --line-buffered 刷新输出每一行 -H, --with-filename 当搜索多个文件时,显示匹配文件名前缀 -h, --no-filename 当搜索多个文件时,不显示匹配文件名前缀 --label=LABEL print LABEL as filename for standard input -o, --only-matching 只显示一行中匹配PATTERN 的部分 -q, --quiet, --silent 不显示任何东西 --binary-files=TYPE 假定二进制文件的TYPE 类型; TYPE 可以是`binary', `text', 或`without-match' -a, --text 匹配二进制的东西 -I 不匹配二进制的东西 -d, --directories=ACTION 目录操作,读取,递归,跳过 -D, --devices=ACTION 设置对设备,FIFO,管道的操作,读取,跳过 -R, -r, --recursive 递归调用 --include=PATTERN 只查找匹配FILE_PATTERN 的文件 --exclude=PATTERN 跳过匹配FILE_PATTERN 的文件和目录 --exclude-from=FILE 跳过所有除FILE 以外的文件 -L, --files-without-match 匹配多个文件时,显示不匹配的文件名 -l, --files-with-matches 匹配多个文件时,显示匹配的文件名 -c, --count 显示匹配的行数 -Z, --null 在FILE 文件最后打印空字符 文件控制: -B, --before-context=NUM 打印匹配本身以及前面的几个行由NUM控制 -A, --after-context=NUM 打印匹配本身以及随后的几个行由NUM控制 -C, --context=NUM 打印匹配本身以及随后,前面的几个行由NUM控制 -NUM 根-C的用法一样的 --color[=WHEN], --colour[=WHEN] 使用标志高亮匹配字串; -U, --binary 使用标志高亮匹配字串; -u, --unix-byte-offsets 当CR 字符不存在,报告字节偏移(MSDOS 模式)
实例
1、在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:
[root@localhost test]# grep test test* #查找前缀有“test”的文件包含“test”字符串的文件
testfile1:This a Linux testfile! #列出testfile1 文件中包含test字符的行 testfile_2:This is a linux testfile! #列出testfile_2 文件中包含test字符的行 testfile_2:Linux test #列出testfile_2 文件中包含test字符的行
2、以递归的方式查找符合条件的文件。例如,查找指定目录/etc/acpi 及其子目录(如果存在子目录的话)下所有文件中包含字符串"update"的文件,并打印出该字符串所在行的内容,使用的命令为:
[root@localhost test]# grep -r update /etc/acpi #以递归的方式查找“etc/acpi”
#下包含“update”的文件 /etc/acpi/ac.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of IO.) Rather than /etc/acpi/resume.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of IO.) Rather than /etc/acpi/events/thinkpad-cmos:action=/usr/sbin/thinkpad-keys--update
3、反向查找。前面各个例子是查找并打印出符合条件的行,通过"-v"参数可以打印出不符合条件行的内容。查找文件名中包含 test 的文件中不包含test 的行,此时,使用的命令为:
[root@localhost test]# grep -v test* #查找文件名中包含test 的文件中不包含test 的行
testfile1:helLinux! testfile1:Linis a free Unix-type operating system. testfile1:Lin testfile_1:HELLO LINUX! testfile_1:LINUX IS A FREE UNIX-TYPE OPTERATING SYSTEM. testfile_1:THIS IS A LINUX TESTFILE! testfile_2:HELLO LINUX! testfile_2:Linux is a free unix-type opterating system.
4、匹配以HELLO开头或者以test开头的行,注意反斜杠,根上面一个例子一样,-e默认是省去的
[root@localhost test]# cat test |grep -e '^(HELLO|test)'
HELLO LINUX!
test Linux !
5、匹配以sui开头,只含有字母
[root@localhost test]# echo 'suixinnan' |grep '^sui[a-z]*$' suixinnan
新建测试文件
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false,aaa,bbbb,cccc,aaaaaa DADddd:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false &nobody:$:99:99:nobody:/:/bin/false suixinnan:x:1000:100:,,,:/home/suixinnan:/bin/bash http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false aaa:x:1001:1001::/home/aaa:/bin/bash test:x:1003:1003::/home/test:/bin/bash policykit:x:102:1005:Po
a,匹配以bin开头的行,用的egrep,在这里可以换成-F,-G
[root@localhost test]# cat test |grep -E '^bin' bin:x:1:1:bin:/bin:/bin/false,aaa,bbbb,cccc,aaaaaa
b,在匹配的行前面加上该行在文件中,或者输出中所在的行号
[root@localhost test]# cat test|grep -n suixin 7:suixinnan:x:1000:100:,,,:/home/suixinnan:/bin/bash
c,不匹配以bin开头的行,并显示行号
[root@localhost test]# cat test|grep -nv '^bin' root:x:0:0:root:/root:/bin/bash DADddd:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false &nobody:$:99:99:nobody:/:/bin/false suixinnan:x:1000:100:,,,:/home/suixinnan:/bin/bash http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false aaa:x:1001:1001::/home/aaa:/bin/bash test:x:1003:1003::/home/test:/bin/bash policykit:x:102:1005:Po
d,显示匹配的个数,不显示内容
[root@localhost test]# cat test|grep -c sui 1
e,匹配system,没有加-i没有匹配到东西。
[root@localhost test]# grep system test [root@localhost test]# grep -ni system test 9:dbus:x:81:81:System message bus:/:/bin/false
f,匹配sui没有匹配到东西,匹配suixinnan能匹配到,因为在test文件中,有suixinnan这个单词
[root@localhost test]# cat test|grep -w sui [root@localhost test]# cat test|grep -w suixinnan suixinnan:x:1000:100:,,,:/home/suixinnan:/bin/bash
g,在这里-x后面东西,和输出中的整行相同时,才会输出
[root@localhost test]# echo "aaaaaa" |grep -x aaa [root@localhost test]# echo "aaaa" |grep -x aaaa aaaa
h,最多只匹配一次,如果把-m 1去掉的话,会有多个(前提test 文件中有多个)
[root@localhost test]# cat test |grep -m 1 suixin suixinnan:x:1000:100:,,,:/home/suixinnan:/bin/bash
i,匹配行的前面显示块号,这个块号是干什么的,不知道,有谁知道可否告诉我一下
[root@localhost test]# cat test |grep -b suixin 241:suixinnan:x:1000:100:,,,:/home/suixinnan:/bin/bash
j,多文件匹配时,在匹配的行前面加上文件名
[root@localhost test]# grep -H 'root' test test2 testbak test:root:x:0:0:root:/root:/bin/bash test2:root testbak:root:x:0:0:root:/root:/bin/bash
k,多文件匹配时,在匹配的行前面不加上文件名
[root@localhost test]# grep -h 'root' test test2 testbak root:x:0:0:root:/root:/bin/bash root root:x:0:0:root:/root:/bin/bash
l,多文件匹配时,显示匹配文件的文件名
[root@localhost test]# grep -l 'root' test test2 testbak DAta test test2 testbak
m,没有-o时,有一行匹配,这一行里面有3个root,加上-o后,这个3个root就出来了
[root@localhost test]# grep 'root' test root:x:0:0:root:/root:/bin/bash [root@localhost test]# grep -o 'root' test root root root
n,递归显示匹配的内容,在test目录下面建个mytest目录,copy test目录下面的test文件到mytest下面,能看到上面的结果
[root@localhost test]# grep test -R /tmp/test/mytest /tmp/test/mytest/test:test:x:1003:1003::/home/test:/bin/bash /tmp/test/mytest/test:@zhangying:*:1004:1004::/home/test:/bin/bash
o,显示匹配root后面的3行
[root@localhost test]# cat test |grep -A 3 root
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false,aaa,bbbb,cccc,aaaaaa daemon:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false
场景:
系统报警显示了时间,但是日志文件太大无法直接 cat 查看。(查询含有特定文本的文件,并拿到这些文本所在的行)
解决:
[root@localhost test]#grep -n '2020-08-24 00:01:11' *.log
从根目录开始查找所有扩展名为 .log 的文本文件,并找出包含 "ERROR" 的行:
[root@localhost test]# find / -type f -name "*.log" | xargs grep "ERROR"
从当前目录开始查找所有扩展名为 .in 的文本文件,并找出包含 "thermcontact" 的行:
[root@localhost test]#find . -name "*.in" | xargs grep "thermcontact"
递归从所有文件中查询匹配的内容,文件名可不同
[root@localhost test]# grep -R C1079651000621 * 20200727/503/20200701000104001317.xml: C1079651000621 20200727/503/20200701000104001317.xml: C1079651000621 20200727/503/20200701000104001333.xml: C1079651000621
有一点要注意,您必需提供一个文件过滤方式(搜索全部文件的话用 *)。如果您忘了,’grep’会一直等着,直到该程序被中断。如果您遇到了这样的情况,按 ,然后再试。
下面还有一些有意思的命令行参数:
grep -i pattern files :不区分大小写地搜索。默认情况区分大小写, grep -l pattern files :只列出匹配的文件名, grep -L pattern files :列出不匹配的文件名, grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’), grep -C number pattern files :匹配的上下文分别显示[number]行, grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行, 例如:grep "abc|xyz" testfile 表示过滤包含abc或xyz的行 grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。 grep -n pattern files 即可显示行号信息 grep -c pattern files 即可查找总行数 还有些用于搜索的特殊符号:< 和 > 分别标注单词的开始与结尾。 例如: grep man * 会匹配 ‘Batman’、’manic’、’man’等, grep ‘<man’ * 匹配’manic’和’man’,但不是’Batman’, grep ‘<man>’ 只匹配’man’,而不是’Batman’或’manic’等其他的字符串。 ‘^’: 指匹配的字符串在行首, ‘$’: 指匹配的字符串在行 尾, 用grep查找结构体 grep -R "struct task_struct {" /usr/src 加-n可以显示行号PS1=$ 进入到家目录在.bashrc 中