Linux常用命令-grep

命令

grep

描述

print lines matching a pattern
过滤显示匹配关键字的行

用法

1
2
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
Options:
-E 使用扩展的正则表达式
-G 使用基本的正则表达式(默认)
-e 使用多个正则表达式匹配
-f 读取文件中的表达式,可以写多行,会依次匹配每一行,使用#号可以注释单行
-i 忽略大小写
-w 匹配整个单词
-x 匹配整行
-s 不显示错误消息
-v 反向匹配,即显示没有匹配到的行
-m 在匹配到第几个后停止
-n 显示行号
-H 显示文件名
-h 不显示文件名
-o 只显示匹配到的内容,可用于数量统计
-q 静默模式,不显示任何输出,可用于条件判断语句,0则表示找到了匹配的行
-r 递归匹配目录,但是不包括软链接
-R 递归匹配目录,并且跟随软链接跳转
-L 只显示没有匹配到的文件名,不显示匹配内容
-l 只显示匹配到的文件名,不显示匹配内容
-c 统计匹配到的行数
-B 显示匹配到的行和该行的前几行
-A 显示匹配到的行和该行的后几行
-C 同时显示匹配到的行的前后几行,可以简写为-NUM,如-C 3简写为-3
--color=auto 高亮显示匹配到的字符,可选参数为always,never,auto
--include=FILE_PATTERN 指定包含哪些文件或目录,支持正则匹配文件名
--exclude=FILE_PATTERN 排除哪些文件
--exclude-dir=PATTERN 排除指定目录

正则表达式REGEXP:由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配符的功能
元字符(metacharacters)是用来阐释字符表达式意义的字符,简言之,元字符就是描述字符的字符,它用于对字符表达式的内容、转换及各种操作信息进行描述
正则表达式(regular expression)就是用一个"字符串"来描述一个特征,然后去验证另一个"字符串"是否符合这个特征

正则表达式元字符
^ 匹配行首,如^abc匹配所有以abc开头的行
$ 匹配行尾,如abc$匹配所有以abc结尾的行
^$ 匹配空行
^[[:space:]]*$ 匹配空白行,包括空格或tab所占的行
. 匹配除换行符(\n,\r)之外的任意单个字符,如a.c匹配abc,a2c等
* 匹配零个或多个先前字符,即匹配次数>=0次,如a*c匹配ac,aac,aaac等
.* 匹配任意长度的任意字符,如a.*c匹配ac,abc,aabbcc等
? 匹配零个或一个先前的字符,即匹配次数<=1次,如a?c匹配c,ac
+ 匹配一个或多个先前的字符,即匹配次数>=1次,如a+c匹配ac,aac,aaac等
| 或匹配,如a|b|c匹配a或b或c
() 分组,如abc([1-9])?匹配abc,abc1,abc123
[] 匹配指定范围内的任意单个字符,如[Aa]bc匹配Abc,abc
[^] 取反,匹配指定范围之外的任意单个字符,如[^Aa]bc匹配除了Abc和abc之外
\ 转义符,如\$匹配$本身
\< 匹配单词词首,如\<abc匹配以abc开头的单词
\> 匹配单词词尾,如abc\>匹配以abc结尾的单词
{n} 匹配n次,如a{2}匹配aa
{n,} 至少匹配n次,即>=n次,如a{2,}匹配aa,aaa等
{n,m} 匹配n-m次,包括n次和m次,即[n-m]次,其中n<=m,如a{2,4}匹配aa,aaa,aaaa
{,m} 最多匹配m次,即<=m次,如ab{,2}匹配a,ab,abb
\b 匹配单词边界,如\broot\b匹配单词root
\B 匹配非单词边界,如root\B匹配rooter而不匹配root
\w 匹配字母,数字和下划线,等同于[A-Za-z0-9_]
\W 匹配非\w的字符
\s 匹配空白字符

基本正则表达式的特殊符号需要\转义,在扩展正则表达式中不需要
分组括号中的模式匹配到的内容会被正则表达式引擎记录到内部变量中,最多可以匹配9个模式,命名为\1...\9
分组匹配后项引用(...)(...)\1\2,\1表示从左侧起第一组括号里的模式所匹配到的字符,\2第二组括号,依次往后

POSIX字符
[[:alnum:]] 匹配任意一个字母或数字,同[0-Z]零-大写Z
[[:alpha:]] 任意一个大小写字母,同[a-Z]小写a-大写Z
[[:lower:]] 任意小写字母
[[:upper:]] 任意大写字母
[[:blank:]] 水平空白字符(空格和制表符)
[[:space:]] 水平或垂直空白字符(比[:blank:]包含的范围广),同[\t\r\n\v\f]
[[:cntrl:]] 任意一个控制字符(ASCII字符集中的前32个字符,退格,删除,警铃...),不可打印字符
[[:digit:]] 任意一个数字,同[0-9]
[[:xdigit:]] 任意一个十六进制数,同[0-9a-F]
[[:graph:]] 任意一个可打印的非空白字符
[[:print:]] 任意一个可打印字符
[[:punct:]] 任意标点符号

注意

推荐使用grep -E和grep -F来替代egrep和fgrep命令
PATTERN如果是表达式或多个单词时,需要用引号括起来,可以是单引号’’也可双引号””,但是单引号无法引用变量

Shell正则表达式
https://man.linuxde.net/docs/shell_regex.html
正则表达式特性支持对比
https://deerchao.cn/tutorials/regex/diffs.html

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
$ more file
aaa
abc
123
abcabc 123
456
aaa
bb
AAA
BB
cc
# 标准正则过滤
$ grep aaa file
aaa
aaa
# 扩展正则
$ grep -E "aaa|abc" file
aaa
abc
abcabc 123
aaa
# 效果同上
$ grep -e "aaa" -e "abc" file
aaa
abc
abcabc 123
aaa
# 多重过滤-且
grep aaa file | grep bbb
# 多重过滤-或
grep -e aaa -e bbb file
# 忽略大小写
$ grep -i aaa file
aaa
aaa
AAA
$ grep abc file
abc
abcabc 123
# 匹配完整单词
$ grep -w abc file
abc
# 匹配完整行
$ grep -x abc file
abc
$ grep [0-9] file
123
abcabc 123
456
# 反向匹配,如下不显示包含数字的行,即只显示纯字母的行
$ grep -v [0-9] file
aaa
abc
aaa
bb
AAA
BB
cc
# 不显示包含大小写字母的行,即只显示纯数字的行
$ grep -Ev [a-Z]+ file
123
456
# 指定多个匹配条件到一个文件中,然后引用这个文件,#号行表示注释
$ more a
#bb
a.c
a.a
$ grep -f a file
aaa
abc
abcabc 123
aaa
# 显示行号
$ grep -n abc file
2:abc
4:abcabc 123
# 匹配到第一个就停止
$ grep -m 1 abc file
abc
# 显示文件名
$ grep -H abc *
aaa:abc
aaa:abcabc 123
file:abc
file:abcabc 123
$ grep abc file
abc
abcabc 123
# 只要匹配到就显示匹配的内容,如下总共匹配到了3处
$ grep -o abc file
abc
abc
abc
$ grep -o abc file | wc -l
3
# 递归匹配目录,但是不包括软链接
$ grep -r bash /etc/s*l
/etc/skel/.bash_logout:# ~/.bash_logout
/etc/skel/.bash_profile:# .bash_profile
/etc/skel/.bash_profile:if [ -f ~/.bashrc ]; then
/etc/skel/.bash_profile: . ~/.bashrc
/etc/skel/.bashrc:# .bashrc
/etc/skel/.bashrc:if [ -f /etc/bashrc ]; then
/etc/skel/.bashrc: . /etc/bashrc
# 递归匹配目录,并且跟随软链接跳转,如下ssl目录是一个软链接
$ grep -R bash /etc/s*l
/etc/skel/.bash_logout:# ~/.bash_logout
/etc/skel/.bash_profile:# .bash_profile
/etc/skel/.bash_profile:if [ -f ~/.bashrc ]; then
/etc/skel/.bash_profile: . ~/.bashrc
/etc/skel/.bashrc:# .bashrc
/etc/skel/.bashrc:if [ -f /etc/bashrc ]; then
/etc/skel/.bashrc: . /etc/bashrc
/etc/ssl/certs/renew-dummy-cert:#!/bin/bash
$ ll -d /etc/ssl/certs
lrwxrwxrwx. 1 root root 16 Nov 27 05:42 /etc/ssl/certs -> ../pki/tls/certs/

$ ls
a aaa anaconda-ks.cfg file
$ grep abc *
aaa:abc
aaa:abcabc 123
file:abc
file:abcabc 123
# 只显示匹配到的文件名,不显示匹配内容
$ grep -l abc *
aaa
file
# 只显示没有匹配到的文件名
$ grep -L abc *
a
anaconda-ks.cfg
# 统计匹配到的行数
$ grep -c abc *
a:0
aaa:2
anaconda-ks.cfg:0
file:2
$ grep abc *
aaa:abc
aaa:abcabc 123
file:abc
file:abcabc 123
$ grep abc --include=file *
file:abc
file:abcabc 123
$ grep abc --exclude=file *
aaa:abc
aaa:abcabc 123

# 显示匹配到的前2行
$ grep -n -B 2 cc file
8-AAA
9-BB
10:cc
# 显示匹配到的后2行
$ grep -n -A 2 aaa file
1:aaa
2-abc
3-123
--
6:aaa
7-bb
8-AAA
# 显示匹配到的前后各2行
$ grep -n -C 2 bb file
5-456
6-aaa
7:bb
8-AAA
9-BB

$ cat g
gle
ggle
gogle
google
abc
goooogle
goooooooooogle
goooooobbbbbbgle
# *匹配1个或多个o
$ grep -E gooo*gle g
google
goooogle
goooooooooogle
# .*匹配任意个数任意字符
$ grep -E g...*gle g
google
goooogle
goooooooooogle
goooooobbbbbbgle
# ?匹配0个或1个o
$ grep -E "go?gle" g
ggle
gogle
# {4}匹配4个o
$ grep -E "go{4}gle" g
goooogle
# {2,}匹配>=2个o
$ grep -E "go{2,}gle" g
google
goooogle
goooooooooogle
# {1,6}匹配[1-6]个o
$ grep -E "go{1,6}gle" g
gogle
google
goooogle
# {,6}匹配<=6个o,包括0个
$ grep -E "go{,6}gle" g
ggle
gogle
google
goooogle

# 不显示空白行
$ grep -Ev "^[[:space:]]*$" file
# 不显示空行和以#号注释的行
$ grep -Ev "^$|^ *#" file
# 推荐使用,不显示空白行和以#号注释的行,包括以空格或tab组成的空白行,以及以空格或tab开头的#号注释的行
$ egrep -v "^[[:space:]]*$|^[[:space:]]*#" file
# 包含usera或userb的行
$ egrep 'user(a|b)' file
# 包含至少一个ab的行
$ egrep '(ab)+' file
# 包含x或者x后面加数字的行
$ egrep 'x[0-9]?' file
# 第一个^表示行首锚定,第二个在[]里的^表示取反,即排除数字开头
$ egrep \<^[^0-9]abc\>
# 至少包含一个大写字母的行
$ egrep '[A-Z]+' file
# 至少一个数字的行
$ egrep '[0-9]' file
# 包含五个字符, 第一个是大写字母, 最后一个是数字的行
$ egrep '[A-Z]...[0-9]' file
# 包含单词test或Test的行
$ egrep '[tT]est' file
# 通用查找匹配首尾单词相同的行
$ egrep "(^.*)\>.*\<\1$" file
# 匹配IP地址
$ egrep "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\" file
# 查找数值大于60小于90的行
$ egrep "[6-8][0-9]" file

系统中的正则表达式案例学习:
$ yum install policycoreutils-python
$ semanage fcontext -l | more

# 递归搜索指定后缀文件*.conf,匹配关键字logpath
$ grep --include=*.conf -R logpath *