Grep 高效用法实战总结 - 运维笔记

 

grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,能使用正则表达式搜索文本,并把匹配的行打印出来。grep主要作用是过滤出指定的行,指定的行满足什么条件,满足的条件可配合正则表达式来表示,实现强大的文本处理

文本处理工具分类
常用的有:grepegrepfgrep

三者区别
grep: 在没有参数的情况下,只输出符合RE(Regular Expression)字符。
egrep:等同于grep -E,和grep最大的区别就是表现在转义符上, 比如grep 做次数匹配时\{n,m\}, egrep则不需要直接{n,m}。egrep显得更方便简洁。
fgrep:等同于grep -f,但是不能使用正则表达式。所有的字符匹配功能均已消失。

grep格式
grep [option] pattern filename

grep的option选项说明

grep的option选项说明:
--color   显示颜色的参数,即搜索出来的关键字符带有颜色。使用"grep --color 关键字符" 或者 "grep --color=auto 关键字符"。一般配置别名alias grep="grep --color"
-a   不要忽略二进制数据。使用"grep -a 关键字符"
-A   显示符合关键字符的行, 以及其后面的n行。使用 "grep -An 关键字符" 或者 "grep -A n 关键字符"
-b   显示符合关键字符的行, 以及其前后的各n行。使用"grep -bn 关键字符", 注意这个不能使用"grep -b n 关键字符"! 跟-C参数差不多,但是会多打印出行号!!!
-B   显示符合关键字符的行, 以及其前面的n行。 使用 "grep -An 关键字符" 或者 "grep -A n 关键字符"
-c   只输出匹配行的计数。即只显示出匹配关键字符的那行的行数,不显示内容!使用"grep -c 关键字符"
-C   显示符合关键字符的行, 以及其前后的各n行。使用 "grep -Cn 关键字符" 或者 "grep -C n 关键字符"。跟-b参数差不多,-b参数会多打印行号出来!
-d   当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。-d后面跟的是进行的动作,一般是"grep -d read"或"grep -d recure",后面会有小示例说明。
-e   指定字符串作为查找文件内容的关键字符。使用"grep -e 关键字符"。grep -e "正则表达式" 文件
-E   将关键字符为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式!!通常用于满足多个条件中的其中一个条件进行搜索。使用grep -E "条件1|条件2|条件2"
-f   显示两个文件中相同的行。使用 "grep -f filename1 filename2 " 或者 "grep --file filename1 filename2",相等于"cat filename1 filename2|sort|uniq -d",即取交集!
-F   将关键字符视为固定字符串的列表。使用"grep -F 关键字 filename1" 或者 "grep -F 关键字符 filename1 filename2 filenamen", 会显示出来关键字所在的文件的列表。
-G   将关键字符视为普通的表示法来使用。
-h   对多文件搜索关键字符时不显示文件名,只显示关键字符。使用"grep -h 关键字符 filename1 filename2 filenamen", 不显示文件名,只显示关键字符。
-H   对多文件搜索关键字符时显示文件名和关键字符,跟-h参数相反。 使用"grep -H 关键字符 filename1 filename2 filenamen", 显示"文件名:关键字符"。
-i   忽略关键字符的大小写。(跟-y参数相同)。使用"grep -i"
-l   对多文件搜索关键字符时只显示文件名。使用"grep -l 关键字符 filename1 filename2 filenamen",只显示文件名,不显示关键字符。
-L   对多文件搜索关键字符时,只显示不匹配关键字符的文件名。使用"grep -L 关键字符 filename1 filename2 filenamen",只显示不匹配关键字符的文件。
-n   显示匹配关键字符的行号和行内容。使用"grep -n 关键字符 filename"
-q   不显示任何信息。用于if逻辑判断,安静模式,不打印任何标准输出。如果有匹配的内容则立即返回状态值0。
-R/-r   此参数的效果和指定"-d recurse"参数相同。
-s   当搜索关键字符,匹配的文件不存在时不显示错误信息。即不显示不存在或无匹配文本的错误信息。 使用"grep -s 关键字符 filename"
-v   反转或过滤搜索,即过滤出来那些不匹配关键字符的行。使用"grep -v 关键字符"
-w   精准搜索关键字符,即只显示完全匹配关键字符的行,不显示那些包含关键字符的行。使用"grep -w 关键字符", 或者使用grep "\<关键字符\>",或者使用grep "\b关键字符\b"
-x   只显示整行都是关键字符的行。使用"grep -x 关键字符"。
-y   忽略关键字符的大小写。(跟-i参数相同)。"grep -y"。
-o   只输出文件中匹配到的部分, 不会打印多余的内容。
-P   使用perl的正则表达式语法,因为perl的正则更加多元化,能实现更加复杂的场景。典型用法是匹配指定字符串之间的字符。(-e或-E是匹配扩展正则表达式,-P是匹配perl正则表达式)

grep正则表达式元字符集(基本集)

^
匹配行的开始 如:'^grep'匹配所有以grep开头的行。
 
$
匹配行的结束 如:'grep$'匹配所有以grep结尾的行。
 
.
匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。
 
*
匹配零个或多个先前字符 如:'*grep'匹配所有一个或多个空格后紧跟grep的行。 .*一起用代表任意字符。
 
[]
匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。即[mn]表示匹配m或者n关键字符,相当于grep -E "m|n"。注意[]里面不要放太多关键字符,容易混乱!只要放[]里面的都是要匹配的关键字符!
 
[^]
匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-F和H-Z的一个字母,但是包含rep并且rep不在开头(即*req)的行。
 
\(..\)
标记匹配字符,如'\(love\)',love被标记为1。
 
\<
匹配单词的开始,如:'\
 
\>
匹配单词的结束,如'str\>'匹配包含以str结尾的单词的行。通常使用"\<关键字符\>"作为精准匹配,相当于grep -w
 
x\{m\}
重复字符x,m次,如:'o\{5\}'匹配包含5个o的行。
 
x\{m,\}
重复字符x,至少m次,如:'o\{5,\}'匹配至少有5个o的行。
 
x\{m,n\}
重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配5--10个o的行。
 
\w
匹配文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。
 
\W
\w的反置形式,匹配一个或多个非单词字符,如点号句号等。
 
\b
单词锁定符,如: \byang\b 表示只匹配yang。相当于grep -w "yang" 或者 grep "\<yang\>"

+
匹配一个或多个先前的字符。如:'[a-z]+able',匹配一个或多个小写字母后跟able的串,如loveable,enable,disable等。注意:先前字符必须使用()或[]括起来,并且使用grep -E。
 
?
匹配零个或一个先前的字符。如:'(gr)?p'匹配gr后跟一个或没有字符,然后是p的行。注意:先前字符必须使用()或[]括起来,并且使用grep -E。
 
a|b|c
匹配a或b或c。如grep -E "a|b|c", 匹配a或b或c中的任意一个都可以。grep -v "a\|b\|c" 或 egrep -v "a|b|c" 过滤掉a或b或c中的任意一个进行搜索。
 
()
分组符号,如:love(able|rs)ov+匹配loveable或lovers,匹配一个或多个ov。


=========================================================================
几个小示例:
[root@ss-server ~]# cat sys.list 
AFG
AFS
BAU
CdC
000823
ERU
jNNNA
IFI
entegor
jKL
NNN
MYSQL
QQQ
UUU
CCS
ONLINE
MPB
IFF

如下,"A.."表示以A开头,后面跟两个单个字符。"."表示任意单个字符。
[root@ss-server ~]# cat sys.list |grep "A.."  
AFG
AFS

重复N字母,至少重复了3次。
[root@ss-server ~]# cat sys.list|grep "N\{3\}"
jNNNA
NNN

如果匹配正则表达式,效果如下:
[root@ss-server ~]# cat sys.list|grep "^[A-Z]\{6\}"   #至少连续出现6次大写的字母
ONLINE
[root@ss-server ~]# cat sys.list|grep "^[A-Z]\{6,6\}"
ONLINE
[root@ss-server ~]# cat sys.list|grep "^[A-Z]\{5\}"  
MYSQL
ONLINE
[root@ss-server ~]# cat sys.list|grep "^[A-Z]\{5,6\}"
MYSQL
ONLINE
[root@ss-server ~]# cat sys.list|grep "^[A-Z]\{3\}"  
AFG
AFS
BAU
ERU
IFI
NNN
MYSQL
QQQ
UUU
CCS
ONLINE
MPB
IFF
[root@ss-server ~]# cat sys.list|grep "^[A-Z]\{3,3\}"
AFG
AFS
BAU
ERU
IFI
NNN
MYSQL
QQQ
UUU
CCS
ONLINE
MPB
IFF

POSIX字符类   (注意使用的时候,外面要套一层中括号才能生效)
为了在不同国家的字符编码中保持一致,POSIX(The Portable Operating System Interface)增加了特殊的字符类,如[:alnum:]是A-Za-z0-9的另一个写法。要把它们放到[]号内才能成为正则表达式,如[A- Za-z0-9]或[[:alnum:]]。在linux下的grep除fgrep外,都支持POSIX的字符类。

[:alnum:]
文字数字字符。使用 grep [[:alnum:]] filename 表示打印filename文件中包括数字和字母(大小写字母)的行

[:alpha:]
文字字符。使用 grep [[:alpha:]] filename 表示打印filename文件中包括字母(大小写字母)的行。

[:digit:]
数字字符。使用 grep [[:digit:]] filename 表示打印filename文件中包括数字的行。

[:graph:]
非空字符(非空格、控制字符)

[:lower:]
小写字符。使用 grep [[:lower:]] filename 表示打印filename文件中包括小写字母的行。

[:cntrl:]
控制字符

[:print:]
非空字符(包括空格)

[:punct:]
标点符号

[:space:]
所有空白字符(新行,空格,制表符)。例如使用 sed -i 's/[[:space:]]//g' filename 表示删除filename文件中所有的空格。

[:upper:]
大写字符。 使用 grep [[:upper:]] filename 表示打印filename文件中包括大写字母的行。

[:xdigit:]
十六进制数字(0-9,a-f,A-F)

grep引号使用问题

单引号:
即将单引号中内容原样输出,也就是单引号''是全引用。

双引号: 
如果双引号的内容中有命令、变量等,会先把变量、命令解析成结果,再将结果输出。双引号""是部分引用。

单双引号:
常量用单引号''括起,而含有变量则用双引号""括起。单双可同时出现,单扩住双。

"" 号里面遇到$,\等特殊字符会进行相应的变量替换
'' 号里面的所有字符都保持原样

对于字符串,双引号和单引号两者相同, 匹配模式也大致相同, 但有一些区别非常容易混淆, 例如:
grep "$a" file    #引用变量a,查找变量a的值。双引号识别变量。
grep '$a' file    #查找"$a"字符串。单引号不识别变量。

grep "\\" file    #grep: Trailing backslash(不知原因)
grep '\\' file    #查找‘\’字符

$  美元符
\  反斜杠
`  反引号
" 双引号
这四个字符在双引号中是具有特殊含义的,其他都没有,而单引号使所有字符都失去特殊含义!

如果用双引号,查找一个\,就应该用四个\:
grep "\\\\" file 这样就对了,这样等同于:
grep '\\' file

第一条命令shell把四个\,转义成2个\传递给grep,grep再把2个\转义成一个\查找;
第二条命令shell没转义,直接把2个\传递给grep,grep再把2个\转义成一个\查找;
其实grep执行的是相同的命令。

grep -E 与 grep -P区别  正则中的 ?=?<=?!?<! ]

grep -E  主要是用来支持扩展正则表达式,比如 | 符号,用于grep多条件查询,并非是使用标准正则表达式。
grep -P  主要让grep使用perl的正则表达式语法,因为perl的正则更加多元化,能实现更加复杂的场景。最典型的用法是"匹配指定字符串之间的字符"。

示例如下:
打印test.file文件中含有2018 或 2019 或 2020字符串的行
[root@localhost ~]# grep -E "2018|2019|2020" test.file

如下想在一句话"Hello,my name is kevin" 中匹配中间的一段字符串 "my name is",可以这样写正则表达式:
[root@localhost ~]# echo "Hello,my name is kevin"
Hello,my name is kevin
[root@localhost ~]# echo "Hello,my name is kevin"|grep -P '(?<=Hello)'
Hello,my name is kevin
[root@localhost ~]# echo "Hello,my name is kevin"|grep -P '(?<=Hello).*(?= kevin)' 
Hello,my name is kevin
[root@localhost ~]# echo "Hello,my name is kevin"|grep -Po '(?<=Hello).*(?= kevin)'
,my name is
[root@localhost ~]# echo "Hello,my name is kevin"|grep -P '(?<=Hello,).*(?= kevin)' 
Hello,my name is kevin
[root@localhost ~]# echo "Hello,my name is kevin"|grep -Po '(?<=Hello,).*(?= kevin)'
my name is

这里千万注意下:正则中的 ?= 、?<= 、?! 、?<! 四个表达的意思。结合grep使用的时候,一定要跟上-P参数,"grep -P" 表示后面跟正则表达式。
?=     表示询问后面跟着的东西是否等于这个。
?<=    表示询问是否以这个东西开头。
?!     表示询问后面跟着的东西是否不是这个。
?<!   表示询问是否不是以这个东西开头 。

示例:grep -P后面跟上面四种正则时,要在引号里使用小括号进行匹配。
[root@localhost ~]# cat test.txt              
bac
ab
bb
bch
ban
[root@localhost ~]# grep -P 'b(?=a)' test.txt 
bac
ban
[root@localhost ~]# grep -P '(?<=a)' test.txt               
bac
ab
ban
[root@localhost ~]# grep -P '(?<=a)b' test.txt             
ab
[root@localhost ~]# grep -P 'b(?!a)' test.txt 
ab
bb
bch
[root@localhost ~]# grep -P '(?<!a)b' test.txt 
bac
bb
bch
ban

按照上面的思路,如果想要取得本机ip地址,可以如下操作:
[root@localhost ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.60.232  netmask 255.255.255.0  broadcast 172.16.60.255
        inet6 fe80::e825:b3ff:fef6:1398  prefixlen 64  scopeid 0x20<link>
        ether ea:25:b3:f6:13:98  txqueuelen 1000  (Ethernet)
        RX packets 22911237  bytes 4001968461 (3.7 GiB)
        RX errors 0  dropped 17058008  overruns 0  frame 0
        TX packets 670762  bytes 98567533 (94.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# ifconfig eth0|grep -P "(?<=inet).*(?=netmask)"
        inet 172.16.60.232  netmask 255.255.255.0  broadcast 172.16.60.255
[root@localhost ~]# ifconfig eth0|grep -Po "(?<=inet).*(?=netmask)"
 172.16.60.232

grep 常用操作技巧                                                                        
1)在文件中搜索一个单词,命令会返回一个包含"match_pattern"的文本行:
[root@test ~]# grep match_pattern file_name
2)在多个文件中查找:
[root@test ~]# grep "match_pattern" file_1 file_2 file_3 ...
3)输出除之外的所有行 -v 选项:
[root@test ~]# grep -v "match_pattern" file_name
4)标记匹配颜色 --color=auto 选项:
[root@test ~]# grep "match_pattern" file_name --color=auto
5)使用正则表达式 -E 选项:
[root@test ~]# grep -E "[1-9]+"

[root@test ~]# egrep "[1-9]+"
6) 只输出文件中匹配到的部分 -o 选项:
[root@test ~]# echo this is a test line. | grep -o -E "[a-z]+\."
line.
[root@test ~]# echo this is a test line. | egrep -o "[a-z]+\."
line.
7)统计文件或者文本中包含匹配字符串的行数 -c 选项:
[root@test ~]# grep -c "text" file_name
8)输出包含匹配字符串的行数 -n 选项:
[root@test ~]# grep "text" -n file_name

[root@test ~]# cat file_name | grep "text" -n
9)多个文件
[root@test ~]# grep "text" -n file_1 file_2
10)打印样式匹配所位于的字符或字节偏移:
[root@test ~]# echo gun is not unix | grep -b -o "not"
7:not
#一行中字符串的字符便宜是从该行的第一个字符开始计算,起始值为0。选项 -b -o 一般总是配合使用。
11)搜索多个文件并查找匹配文本在哪些文件中:
[root@test ~]# grep -l "text" file1 file2 file3...

grep递归搜索文件                                                                                
12)在多级目录中对文本进行递归搜索:
[root@test ~]# grep "text" . -r -n
.表示当前目录。
13)忽略匹配样式中的字符大小写:
[root@test ~]# echo "hello world" | grep -i "HELLO"
hello
14)选项 -e 制动多个匹配样式:
[root@test ~]# echo this is a text line | grep -e "is" -e "line" -o
is
is
line
15)也可以使用-f选项来匹配多个样式,在样式文件中逐行写出需要匹配的字符。
[root@test ~]# cat patfile
aaa
bbb
[root@test ~]# echo aaa bbb ccc ddd eee | grep -f patfile -o

在grep搜索结果中包括或者排除指定文件                                              
16)只在目录中所有的.php和.html文件中递归搜索字符"main()"
[root@test ~]# grep "main()" . -r --include *.{php,html}
17)在搜索结果中排除所有README文件
[root@test ~]# grep "main()" . -r --exclude "README"
18)在搜索结果中排除filelist文件列表里的文件
[root@test ~]# grep "main()" . -r --exclude-from filelist
19)使用0值字节后缀的grep与xargs:
#测试文件:
[root@test ~]# echo "aaa" > file1
[root@test ~]# echo "bbb" > file2
[root@test ~]# echo "aaa" > file3
[root@test ~]# grep "aaa" file* -lZ | xargs -0 rm
20)执行后会删除file1和file3,grep输出用-Z选项来指定以0值字节作为终结符文件名(\0),xargs -0 读取输入并用0值字节终结符分隔文件名,然后删除匹配文件,-Z通常和-l结合使用。"grep -q"用于if逻辑判断,特别好用!-q 参数意为安静模式,不打印任何标准输出。如果有匹配的内容则立即返回状态值0。
grep -q 静默输出:
[root@test ~]# grep -q "test" filename
不会输出任何信息,如果命令运行成功返回0,失败则返回非0值。一般用于if条件测试。

如下是某个脚本中使用的"grep -q"安静模式
#Deploy_Env参数有下划线则对Pkg_Env和Deploy_Env重新赋值
if `echo ${Deploy_Env}|grep -q  "_"`;then
    Pkg_Env=`echo ${Deploy_Env} | awk -F'_' '{print $2}'`
    Deploy_Env=`echo ${Deploy_Env} | awk -F'_' '{print $1}'`
fi

再如下一例
[root@test ~]# if $(echo "wang_shibo"|grep -q "_");then kevin=`echo "wang_shibo"|awk -F"_" '{print $2}'`;echo ${kevin};fi
shibo

打印出匹配文本之前或者之后的行                                                       
21)显示匹配某个结果之后的3行,使用 -A 选项:
[root@test ~]# seq 10 | grep "5" -A 3
5
6
7
8
22)显示匹配某个结果之前的3行,使用 -B 选项:
[root@test ~]# seq 10 | grep "5" -B 3
2
3
4
5
23)显示匹配某个结果的前三行和后三行,使用 -C 选项:
[root@test ~]# seq 10 | grep "5" -C 3
2
3
4
5
6
7
8
24)如果匹配结果有多个,即多重匹配的话,中间会用"--"作为各匹配结果之间的分隔符:
[root@test ~]# echo -e "a\nb\nc\na\nb\nc" | grep a -A 1
a
b
--
a
b
[root@test ~]# grep "match_pattern" file_name

grep取文件中每行的前两个字符/前2字节                                                

示例:
[root@localhost tmp]# cat test 
00c3dd43f15eafab3b0db4bdaabb3f6d91c2f9a3b88e044ddf83393dd910eb9b 
fb0772b142fe0d214c0ccfa9c7b8ed13277c35e9fce75ba1c151dd878dcda95c
d7c3167c320d7a820935f54cf4290890ea19567da496ecf774e8773b35d5f065
131f805ec7fd68d45a887e2ef82de61de0247b4eb934ab03b7c933650e854baa
322ed380e680a77f30528ba013e3a802a7b44948a0609c7d1d732dd46a9a310d
6ac240b130982ad1c3ba3188abbf18ba4e54bdd9e504ce2d5c2eff6d3e86b8dd
af40529340df51a38ca319c40e6b718f5952990b335aa703967520809061f677
a1bbb86f4147e007af7d3f7e987cf5ed3d33912bf430d8ab3528b1953225cca6
10ebb929a9def601aa26150b2dadb6eae47ad07ac399e25ace3a5c1395fb2794

[root@localhost tmp]# cat /tmp/test|grep -o "^.\{0,2\}"
00
fb
d7
13
32
6a
af
a1
10

grep同时筛选多个条件                                                                        

grep使用-E参数实现"满足多个条件中的任意一个",如下:
1)满足任意条件(word1、word2和word3之一)将匹配。
# grep -E "word1|word2|word3"  file.txt
 
grep要想实现"同时满足多个条件",需要执行多个grep过滤命令,如下:
2)必须同时满足三个条件(word1、word2和word3)才匹配。
# grep word1 file.txt | grep word2 |grep word3
# cat file.txt|grep word1 | grep word2 |grep word3
    
简单总结下grep常用过滤命令:
过滤的内容可以是一个词组等, 需要用引号包裹
1)获取文件中的关键字key:  # cat fileName | grep "key"   #即获取fileName文件中的key字符
2)获取文件中的某个关键字key1, key2, key3:   # cat fileName | grep -E "key1|key2|key3"    #即获取fileName文件中的key1或key2或key3字符,满足一个条件即可获取!
3)获取文件中的多个关键字,同时满足:  # cat fileName | grep key1 | grep key2| grep key3    #即同时获取fileName文件中的key1,key2和key3,必须同时满足所有条件才可获取!
4)忽略文件中的某个关键字, 需要转义"|":   # cat fileName | grep -v "key1\|key2\|key3"     #即过滤掉fileName文件中的key1或key2或key3,满足一个条件即可过滤!
4)忽略文件中的多个关键字,:   # cat fileName | grep -v "key1"| grep -v "key2"| grep -v "key3"  #即过滤掉fileName文件中的key1,key2和key3,必须同时满足所有条件才可过滤!
 
grep常用的还有:
grep -i:表示不区分大小写
grep -w:精准匹配   [或者使用单字边界"\<\>"或锁定单词"\b\b",即grep -w "str" 相等于 grep "\<str\>" 相当于 grep "\bstr\b"]
grep -An:获取匹配关键字所在行的后n行
grep -Bn:获取匹配关键字所在行的前n行
grep -Cn:获取匹配关键字所在行的前后各n行

另外注意:
grep -v "条件1\|条件2\|条件3"   #需要加转义符
egrep -v "条件1|条件2|条件3"    #不需要加转义符
=============================================================================
示例如下:
1)排除test.txt文件中的haha、hehe字符
# cat test.txt |grep -v "haha\|hehe"
 
2)删除/opt/data目录下创建时间是2017年 或 2018年的文件("ls -l"命令结果中的第8列是文件创建时间、第9列是文件名。需要精准匹配)
[root@localhost ~ ]# ll
total 15996
-rw-r--r-- 1 root root   781301 Nov 11 2017 a.sql
-rw-r--r-- 1 root root   460189 Nov 11 11:20 ncc_20180909.log
-rw-r--r-- 1 root root   112055 Nov 11 23:09 data_txt
-rw-r--r-- 1 root root   730029 Nov 11 2018 gate.tar.gz
.........
 
[root@localhost ~ ]# ls -l|grep -E -w "2017|2018"|xargs rm -rf

grep精确匹配关键字符                                                                        
使用grep搜索某个关键字时,默认搜索出来的是所有包含该关键字的行,如下:
搜索/var/named/veredholdings.cn_zone文件中172.16.50.24所在的行,默认会把所有包括172.16.50.24所在的行打印出来。
[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep 172.16.50.24
devzl-app01         IN    A     172.16.50.243
devzl-app02         IN    A     172.16.50.244
devzl-redis01       IN    A     172.16.50.245
devzl-redis02       IN    A     172.16.50.246
devzl-redis03       IN    A     172.16.50.247
devzl-oracle01     IN    A     172.16.50.242
wiki02                  IN     A     172.16.50.24

[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep 172.16.50.24 --color
devzl-app01         IN    A      172.16.50.243
devzl-app02         IN    A       172.16.50.244
devzl-redis01       IN    A       172.16.50.245
devzl-redis02       IN    A        172.16.50.246
devzl-redis03       IN    A        172.16.50.247
devzl-oracle01     IN    A        172.16.50.242
wiki02                  IN     A        172.16.50.24

[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep -o 172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24

要想精确地搜索出文件中某个单词所在的行,而不是打印所有包括该单词字样的行,可以使用grep -w参数
-w(--word-regexp):表示强制PATTERN仅完全匹配字词
[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep -w 172.16.50.24
wiki02      IN      A      172.16.50.24
或者使用 \<\>单字边界也可以实现精确匹配(注意两边要加上双引号)
[root@uatdns01 named]# cat /var/named/veredholdings.cn_zone|grep "\<172.16.50.24\>"
wiki02      IN     A       172.16.50.24
或者使用单词锁定符\b也可以实现精确匹配
[root@uatdns01 named]# cat /var/named/veredholdings.cn_zone|grep "\b172.16.50.24\b"
wiki02      IN     A       172.16.50.24

两个小面试题
1)精确地找出名为abc的进程名。
# ps -ef|grep -w "abc"
或者
# ps -ef|grep "\<abc\>"
或者
# ps -ef|grep "\babc\b"
2)判断该进程的数量是否在3-5之间。
# ps -ef|grep -w abc|wc -l
或者
# ps -ef|grep "\<abc\>"|wc -l

[[ 需要注意 ]]grep 使用 -w\<\> 或 \b 进行精准匹配时,对于@,- 特殊字符是过滤不掉的,下划线_ 字符可以过滤掉。
示例如下:

小示例1

写一个shell脚本,检查服务器上的main进程在不在
 
[root@two002 tmp]# ps -ef|grep main
root     23448 23422  0 11:40 pts/0    00:00:00 grep --color=auto main
[root@two002 tmp]# ps -ef|grep main|grep -v grep|wc -l
0
  
[root@two002 tmp]# cat /tmp/main_check.sh
#!/bin/bash
NUM=$(ps -ef|grep main|grep -v grep|wc -l)
if [ $NUM -eq 0 ];then
   echo "It's not good! main is stoped!"
else
   echo "Don't worry! main is running!"
fi
 
 
执行检查脚本
[root@two002 tmp]# sh -x /tmp/main_check.sh
++ grep main
++ grep -v grep
++ wc -l
++ ps -ef
+ NUM=2
+ '[' 2 -eq 0 ']'
+ echo 'Don'\''t worry! main is running!'
Don't worry! main is running!
 
[root@two002 tmp]# sh /tmp/main_check.sh
Don't worry! main is running!
 
 
如上发现,执行脚本/tmp/main_check.sh的过程中,看到NUM参数值是2!
但是手动执行ps -ef|grep main|grep -v grep|wc -l的结果明明是0!!
 
这是由于grep匹配的问题,需要grep进行精准匹配,即"grep -w"
这就需要将main_check.sh脚本内容修改如下:
[root@two002 tmp]# cat /tmp/main_check.sh
#!/bin/bash
NUM=$(ps -ef|grep -w main|grep -v grep|wc -l)
if [ $NUM -eq 0 ];then
   echo "Oh!My God! It's broken! main is stoped!"
else
   echo "Don't worry! main is running!"
fi
 
 
再次执行检查脚本,就正确了
[root@two002 tmp]# sh -x /tmp/main_check.sh
++ grep -w main
++ grep -v grep
++ wc -l
++ ps -ef
+ NUM=0
+ '[' 0 -eq 0 ']'
+ echo 'Oh!My God! It'\''s broken! main is stoped!'
Oh!My God! It's broken! main is stoped!
 
[root@two002 tmp]# sh /tmp/main_check.sh
Oh!My God! It's broken! main is stoped!

小示例2 

[root@localhost ABG]# ll /root/app/script/ansible/config/ABG/*.cfg|head -10
-rw-rw-rw- 1 root root 176 Aug 22 14:26 /root/app/script/ansible/config/ABG/absTag.cfg
-rw-rw-rw- 1 bxi  bxi  435 Jun 11  2019 /root/app/script/ansible/config/ABG/accounting.cfg
-rw-rw-rw- 1 root root 234 Sep  4 16:11 /root/app/script/ansible/config/ABG/accounting_springBoot.cfg
-rw-rw-rw- 1 bxi  bxi  276 Aug  7 15:21 /root/app/script/ansible/config/ABG/adapter.cfg
-rw-rw-rw- 1 bxi  bxi  359 Oct 29 14:47 /root/app/script/ansible/config/ABG/adapter-fe.cfg
-rw-rw-rw- 1 root root 191 Dec 11 15:28 /root/app/script/ansible/config/ABG/aibank-service.cfg
-rw-rw-rw- 1 root root 218 Jun 11  2019 /root/app/script/ansible/config/ABG/aicard-file.cfg
-rw-rw-rw- 1 bxi  bxi  261 Jun 11  2019 /root/app/script/ansible/config/ABG/aicard-mis.cfg
-rw-rw-rw- 1 bxi  bxi  288 Jun 11  2019 /root/app/script/ansible/config/ABG/aicard-service.cfg
-rw-rw-rw- 1 root root 177 Nov 14 09:59 /root/app/script/ansible/config/ABG/aicase.cfg

查看/root/app/script/ansible/config/ABG目录下的cfg结尾的配置文件中是否由带_A的配置,比如:
[root@localhost ABG]# cat /root/app/script/ansible/config/ABG/mir-x-fund.cfg
[mir-x-fund_F]
172.16.60.20

[mir-x-fund_A]
172.16.60.22

[mir-x-fund:children]
mir-x-fund_F
mir-x-fund_A

[mir-x-fund:vars]
deploy_path=/opt/ABG/mir-x-fund/
start_time_out=90
stop_time_out=60
module=mir-x-fund

[root@localhost ABG]# cat /root/app/script/ansible/config/ABG/mir-x-fund.cfg|grep -w "*_A" 
[root@localhost ABG]# cat /root/app/script/ansible/config/ABG/mir-x-fund.cfg|grep -w ".*_A"
[mir-x-fund_A]
mir-x-fund_A

脚本如下(主要用到grep -w ".*_A"):
[root@localhost ABG]# cat /root/ABG_A_file.sh 
#!/bin/bash
for file in $(ls /root/app/script/ansible/config/ABG/*.cfg)
do
   cat ${file}|grep -w ".*_A" >/dev/null 2>&1
   if [ $? -ne 0 ];then
      echo -e "ABG的$(echo ${file}|awk -F"/" '{print $NF}'|awk -F".cfg" '{print $1}')没有A环境的配置。\n配置文件为${file}\n"
   fi
done

执行脚本(配置文件是"应用模块.cfg", ABG系统下的应用模块):
[root@localhost ABG]# sh /root/ABG_A_file.sh
ABG的accounting_springBoot没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/accounting_springBoot.cfg

ABG的aibank-service没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/aibank-service.cfg

ABG的aireader-service没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/aireader-service.cfg

ABG的backend-aiprogram-gateway没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/backend-aiprogram-gateway.cfg

ABG的backend-transation没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/backend-transation.cfg

ABG的backend-visitorguide没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/backend-visitorguide.cfg

ABG的code没有A环境的配置。
配置文件为/root/app/script/ansible/config/ABG/code.cfg

grep高效搜索用法大全                                                                       

下面以/opt/aa.txt文件搜索为例
[root@ss-server ~]# cat /opt/aa.txt
beijing
beihai
this is test
you are good
   
通过管道过滤ls -l输出的内容,只显示以a开头的行。
[root@ss-server ~]# ls -l | grep '^a'
   
显示所有以d开头的文件中包含test的行。
[root@ss-server ~]# grep 'test' d*
   
显示在aa,bb,cc文件中匹配test的行。
[root@ss-server ~]# grep 'test' aa bb cc
   
显示aa文件中所有包含每个字符串至少有5个连续小写字符的字符串的行。
[root@ss-server ~]# grep '[a-z]\{5\}' aa
   
能够使用-o仅仅打印匹配的字符
[root@ss-server ~]# echo this is line. |grep -o "[a-z]*.$"
line.
[root@ss-server ~]# echo this is line. |grep -o "[a-z]*\."
line.
[root@ss-server ~]# grep -o "bei" /opt/aa.txt
bei
bei
   
打印除匹配行之外的其它行,使用-v:
[root@ss-server ~]# echo -e "1\n2\n3\n4"|grep -v "1\|2\|3"
4
[root@ss-server ~]# grep -v "beihai\|this is test" /opt/aa.txt
beijing
you are good
   
统计匹配字符串的行数。使用-c
[root@ss-server ~]# echo -e "1\n2\n3\n4"|grep -v "1\|2" -c
2
   
统计字符串模式匹配的次数。能够结合-o。
[root@ss-server ~]# echo "beijing is good"|grep -o "bei"
bei
[root@ss-server ~]# echo "beijing is good"|grep -o "i"
i
i
i
   
假设须要显示行号,能够打开-n
[root@ss-server ~]# cat /opt/aa.txt |grep -o "bei" -n
1:bei
2:bei
   
-b选项能够打印出匹配的字符串想对于其所在的行起始位置的偏移量(从0开始)。通常配合-o使用:
[root@ss-server ~]# echo "012333456789" | grep -b -o 4
6:4
[root@ss-server ~]# echo "beijing ai ni"|grep -o "ai" -b
8:ai
[root@ss-server ~]# echo "beijing ai ni"|grep -o "jing" -b
3:jing
   
-P参数(声明grep后面要用的是perl的正则表达式)(\d+ 一个或多个数字)
[root@ss-server ~]# echo -e "\nline.123\nline."|grep -P "[a-z]*\.\d+"
line.123
[root@ss-server ~]# echo -e "\nline.123\nline."|grep -P "[a-z]*\."
line.123
line.
[root@ss-server ~]# echo -e "\nline.123\nline."|grep -P "[a-z]*\.$"
line.
[root@ss-server ~]# echo -e "\nline.123\nline."|grep -P "\.$"
line.
   
匹配多个字符串模式(grep -e 或者 grep -E):
没有-o参数不会只打印匹配项
添加-o参数之后只打印匹配项
[root@ss-server ~]# cat /opt/aa.txt |grep -e "bei" -e "jing" -e "test"
beijing
beihai
this is test
[root@ss-server ~]# cat /opt/aa.txt |grep -e "bei" -e "jing" -e "test" -o
bei
jing
bei
test
   
[root@ss-server ~]# grep -E "bei|jing|test" /opt/aa.txt
beijing
beihai
this is test
[root@ss-server ~]# grep -E "bei|jing|test" -o /opt/aa.txt
bei
jing
bei
test
   
参数oP一起使用,会单独打印出要匹配的数字
[root@ss-server ~]# echo office365 | grep -oP "\d+"
365
[root@ss-server ~]# echo office365 | grep -oP "\d*"
365
[root@ss-server ~]# echo office365 | grep -oP "[0-9]*"
365
[root@ss-server ~]# echo 365beijing23 | grep -oP "\d+"
365
23
[root@ss-server ~]# echo 365beijing23 | grep -oP "\d*"
365
23
[root@ss-server ~]# echo 365beijing23 | grep -oP "[0-9]*"
365
23
   
只有参数-P,会完整显示匹配内容的一行,匹配内容高亮显示
[root@ss-server ~]# echo office365 | grep -P "\d+"
office365
   
只有参数-o,不会匹配任何内容,因为没有声明grep要使用正则表达式
如果单独使用参数-o,后面匹配的要是一个具体的字符串,不是正则
[root@ss-server ~]# echo office365 | grep -o "\d+"
[root@ss-server ~]#
[root@ss-server ~]# echo office365 | grep -o "365"
365
   
-Z选项在输出匹配文件名称时将以/0结尾配合xargs -0能够发挥非常多作用。
如下,将当前路径下包括wang字符串的文件全部删除
[root@ss-server ~]# echo "wang" >>11.txt
[root@ss-server ~]# echo "wangbo" >>12.txt
[root@ss-server ~]# echo "wanghu" >>13.txt
[root@ss-server ~]# echo "liru" >>14.txt
[root@ss-server ~]# grep -lZ "wang" *
11.txt 12.txt 13.txt
[root@ss-server ~]# grep -lZ "wang" *|xargs -0 rm
[root@ss-server ~]# ls
14.txt
   
限定全字匹配选项:-w,即精准匹配,三种方法:-w参数,"\<\>"单字边界,"\b\b"
[root@ss-server ~]# echo "linux" >> aa.list
[root@ss-server ~]# echo "li" >> bb.list
[root@ss-server ~]# grep -rn "li" *.list
aa.list:1:linux
bb.list:1:li
[root@ss-server ~]# grep -w "li" *.list  
bb.list:li
[root@ss-server ~]# grep "\<li\>" *.list
bb.list:li
[root@ss-server ~]# grep "\bli\b" *.list  
bb.list:li
   
"grep -E" 和 egrep 效果等同
[root@ss-server ~]# cat /etc/passwd|grep -E "linan|bobo"
linan:x:1000:1000::/home/linan:/bin/bash
bobo:x:1002:1002::/home/bobo:/bin/bash
   
[root@ss-server ~]# cat /etc/passwd|egrep "linan|bobo"
linan:x:1000:1000::/home/linan:/bin/bash
bobo:x:1002:1002::/home/bobo:/bin/bash
   
"grep -e"参数同样是匹配多个关键字
[root@ss-server ~]# cat /etc/passwd|grep -e "linan" -e "bobo"
linan:x:1000:1000::/home/linan:/bin/bash
bobo:x:1002:1002::/home/bobo:/bin/bash
 
#######################################################################################################################
#######################################################################################################################
grep -q : 安静模式,不打印任何标准输出。用于if逻辑判断,如果有匹配的内容则立即返回状态值0。
[root@localhost ~]# cat test.txt 
 17:41:54 up 67 days, 5 min,  2 users,  load average: 0.00, 0.01, 0.05
[root@localhost ~]# grep -q "days" test.txt
[root@localhost ~]# echo $?
0
[root@localhost ~]# grep -q "days111" test.txt
[root@localhost ~]# echo $?
1
 
[root@localhost ~]# grep -q "days" test.txt && echo ok
ok
[root@localhost ~]# grep -q "days111" test.txt && echo ok
[root@localhost ~]# grep -q "days" test.txt || echo ok    
[root@localhost ~]# grep -q "days111" test.txt || echo ok 
ok
 
"grep -i" 或 "grep -y" 不区分大小写
[root@localhost ~]# echo -e "a\nA\nb\nc"|grep -i "a"
a
A
[root@localhost ~]# echo -e "a\nA\nb\nc"|grep -y "a"
a
A
 
grep使用正则关键匹配
[root@localhost ~]# cat test.txt
abc
adb123
abcde
abcdefg
[root@localhost ~]# cat test.txt|grep -e '[a-z]\{4\}'
abcde
abcdefg
[root@localhost ~]# cat test.txt|grep -e '[a-z]\{5\}'
abcde
abcdefg
[root@localhost ~]# cat test.txt|grep -e '[a-z]\{6\}'
abcdefg
  
grep查找以ab开头的行(使用^)
[root@localhost ~]# grep "^ab" test.txt
 
grep查找以de结尾的行(使用$)
[root@localhost ~]# grep "de$" test.txt
 
grep查找空行(使用^$);查找空行及其行号
[root@localhost ~]# grep "^$" test.txt
[root@localhost ~]# grep -n "^$" test.txt
 
#######################################################################################################################
#######################################################################################################################
grep利用[]搜索集合字符
[] 表示其中的某一个字符 ,例如[ade] 表示a或d或e
[root@localhost ~]# cat test.txt
abc
adb8877
123456
[root@localhost ~]# cat test.txt|grep [8]
adb8877
[root@localhost ~]# cat test.txt|grep [a8]
abc
adb8877
[root@localhost ~]# cat test.txt|grep [85]
adb8877
123456
 
可以用^符号做[]内的前缀,表示除[]内的字符之外的字 符。
比如搜索oo前没有g的字符串所在的行, 使用 '[^g]oo' 作搜索字符串
[root@localhost ~]# cat haha.txt
abc
cbc
3bc
[root@localhost ~]# cat haha.txt|grep "[^a]bc"
cbc
3bc
 
[] 内可以用范围表示,比如[a-z] 表示小写字母,[0-9] 表示0~9的数字, [A-Z] 则是大写字母们。
[a-zA-Z0-9]表示所有数字与英文字符。 当然也可以配合^来排除字符。
^ 表示行的开头,$表示行的结尾( 不是字符,是位置)那么'^$'就表示空行, 因为只有行首和行尾。
注意: ^和$放在[]括号内或[]括号外都可以!!!
[root@localhost ~]# grep [0-9] test.txt         #搜索包含数字的行
[root@localhost ~]# grep [a-z] test.txt         #搜索包含小写字母的行
[root@localhost ~]# grep [a-z0-9] test.txt      #搜索包含数字和小写字母的行
[root@localhost ~]# grep [A-Z] test.txt         #搜索包含大写字母的行 
[root@localhost ~]# grep '^[a-z]' test.txt      #搜索以小写字母开头的行。或者 grep '[^a-z]' test.txt
[root@localhost ~]# grep '^[^a-zA-Z]' test.txt  #搜索开头不是英文字母的行
[root@localhost ~]# grep '\.$' test.txt         #搜索末尾是.的行。由于.是正则表达式的特殊符号,所以要用\转义
 
=====================================
注意:在windows系统下生成的文本文件,换行会加上一个 ^M 字符。所以最后的字符会是隐藏的^M , 故在linux里处理Windows下面的文本时要特别注意!
可以用下面命令来删除^M符号。 ^M==\r
# cat dos_file | tr -d '\r' > unix_file
 
#######################################################################################################################
#######################################################################################################################
.
匹配一个非换行符的字符。即.符号匹配单个字符,能匹配空格
如:'gr.p'匹配gr后接一个任意字符,然后是p。例如'g??d' 可以用 'g..d' 表示。 good ,gxxd ,gabd .....都符合。
   
*
匹配零个或多个先前字符 
如:'*grep'匹配所有一个或多个空格后紧跟grep的行。
如:"aa*"表示搜索一个a以上的字符串!!! 其中第一个a一定存在,第二个a可以有一个或多个,也可以没有,因此代表至少一个a!!
 
.* 一起用代表任意字符
.+ 字符必须出现 1 次 
.? 字符出现 0 次或 1 次
 
[root@localhost ~]#  grep 'g..d' test.txt     #搜索
[root@localhost ~]#  grep 'ooo*' test.txt     #搜索两个o以上的字符串!!前两个o一定存在,第三个o可没有,也可有多个
[root@localhost ~]#  grep 'goo*g' test.txt    #搜索g开头和结尾,中间是至少一个o的字符串,即gog, goog....gooog...等
[root@localhost ~]#  grep 'g.*g' test.txt     #搜索g开头和结尾的字符串在的行。 .*表示 0个或多个任意字符
 
#######################################################################################################################
#######################################################################################################################
{ }  表示限定连续重复字符的范围
 
.* 只能限制0个或多个, 如果要确切的限制字符重复数量,就用{范围} 。范围是数字,用,隔开,比如2,5就表示2~5个;"2"表示2个,"2,"表示2到更多个
 
需要注意:由于{ } 在SHELL中有特殊意义,因此作为正则表达式用的时候要用\转义一下。
 
[root@localhost ~]#  grep 'o\{2\}' test.txt          #搜索包含两个o的字符串的行, 2个或2个以上的o的字符串的行都会搜索出来。'o\{2\}'其实等同于'o\{2,\}'
[root@localhost ~]#  grep 'go\{2,5\}g' test.txt      #搜索g后面跟2~5个o,后面再跟一个g的字符串的行
[root@localhost ~]#  grep 'go\{2,\}g' test.txt       #搜索包含g后面跟2个以上o,后面再跟g的行

搜索test.txt文件中包含2次bo字符串的行 (2个或2个以上的bo字符串都会被打印出来)
[root@localhost ~]# grep -n '\(bo\)\{2\}' test.txt

搜索test.txt文件中至少包含1次bo字符串的行
[root@localhost ~]# grep -n '\(bo\)\{1,\}' test.txt

搜索test.txt文件中出现1~3次包含bo字符串的行
[root@localhost ~]# grep -n '\(bo\)\{1,3\}' test.txt

显示test.txt 文件中至少有5个连续小写字符的字符串的行
[root@localhost ~]# grep -n '[a-z]\{5\}' test.txt
 
需要注意:
如果想让[]括号中的^ - 不表现特殊意义,可以放在[]里面内容的后面。
例如:'[^a-z\.!^ -]' 表示没有小写字母,没有. 没有!, 没有空格,没有- 的 串,注意[]里面有个小空格。
 
另外:shell 里面的反向选择为[!range], 正则里面是 [^range]。正则[^0-9]表示不以数字为开头的字符串。
 

######### grep 的标签 ##########
格式:grep '\(str\)\(\)\(\)[other]\1' filename

[root@localhost ~]# cat -n test1.txt
     1  kevinboaakevin
     2  kevinboeekevin
     3  kevinbocccckevinaabb
[root@localhost ~]# grep -n "\(kevin\)\(bo\)..\1" test1.txt
1:kevinboaakevin
2:kevinboeekevin

[root@localhost ~]# grep 'w\(es\)t.*\1' test.txt
如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着 另外一个es(\1),找到就显示该行。
如果用egrep或grep -E,就不用”\”号进行转义,直接写成'w(es)t.*\1'就可以了。示例如下:
[root@localhost ~]# cat test.txt
westbwest
west123
westasdfwestsdf
[root@localhost ~]# grep 'w\(es\)t.*\1' test.txt
westbwest
westasdfwestsdf
[root@localhost ~]# grep -E 'w(es)t.*\1' test.txt
westbwest
westasdfwestsdf
[root@localhost ~]# egrep 'w(es)t.*\1' test.txt
westbwest
westasdfwestsdf

#######################################################################################################################
#######################################################################################################################
grep 扩展正则表达式是对基础正则表达式添加了几个特殊构成的。
 
例如:去除空白行和行首为#的行
[root@localhost ~]# grep -v '^$' test.txt | grep -v '^#'  
[root@localhost ~]# egrep -v '^$|^#' test.txt  
[root@localhost ~]# grep -v '^$\|^#' test.txt
 
这里列出几个扩展特殊符号:
+   匹配一个或多个先前的字符。如:'[a-z]+able',匹配一个或多个小写字母后跟able的串,如loveable,enable,disable等。注意:先前的字符必须使用()或[]括起来,并且使用grep -E。
?   匹配零个或一个先前的字符。如:'(gr)?p'匹配gr后跟一个或没有字符,然后是p的行。注意:先前的字符必须使用()或[]括起来,并且使用grep -E。
|   表示或关系,比如 'gd|good|dog' 表示有gd,good或dog的串
()  表示将部分内容合成一个单元组。 比如 要搜索 glad 或 good 可以这样 'g(la|oo)d'
 
()的好处是可以对小组使用 + ? * 等。比如要搜索A开头和C结尾,并且中间有至少一个(xyz)的字符串,可以这样 'A(xyz)+C'
 
示例如下(注意要使用grep -E参数,并且先前字符使用()或[]括起来 ):
[root@localhost ~]# grep -E '(gr)?p' test.txt        #搜索匹配gr后跟零个或一个字符,然后是p的行。
[root@localhost ~]# grep -E '[gr]?p' test.txt        #搜索匹配gr后跟零个或一个字符,然后是p的行
[root@localhost ~]# grep -E "(2)?22" test.txt        #搜索匹配2后跟零个或一个字符,然后是22的行
[root@localhost ~]# grep -E "[2]?2" test.txt         #搜索匹配2后跟零个或一个字符,然后是2的行
[root@localhost ~]# grep -E '(2)+' test.txt          #搜索匹配2后跟一个或多个字符的行
[root@localhost ~]# grep -E '(22)+' test.txt         #搜索匹配22后跟一个或多个字符的行
[root@localhost ~]# grep -E '(asd)+' test.txt        #搜索匹配asd后跟一个或多个字符的行
[root@localhost ~]# grep -E 'ab|12|we' test.txt      #搜索匹配ab或12或we字符的行
[root@localhost ~]# grep -v 'ab\|12\|we' test.txt    #搜索不匹配ab或12或we字符的行 (注意|前面加转义符)
[root@localhost ~]# egrep -v 'ab|12|we' test.txt     #搜索不匹配ab或12或we字符的行(注意|前面不加转义符)
[root@localhost ~]# grep -E "glad|good" test.txt     #搜索 glad 或 good
[root@localhost ~]# grep -E "g(la|oo)d" test.txt     #搜索 glad 或 good
[root@localhost ~]# grep -E "g(lay)+h" test.txt      #搜索 g开头,h结尾,并且中间有一个或多个lay字符的行。注意这里lay是一个整体了,比如搜索出glayh,glaylayh

再看下面一例
[root@localhost ~]# cat test1.txt       
boruabcff
beibiaaacsf

nice to
meet you
123
123data
567
[root@localhost ~]# grep "1." test1.txt 
123
123data
[root@localhost ~]# grep "aa*" test1.txt      
boruabcff
beibiaaacsf
123data
[root@localhost ~]# grep "n.+" test1.txt          
[root@localhost ~]# grep -E "n.+" test1.txt    
nice to
[root@localhost ~]# echo "nb" >> test1.txt
[root@localhost ~]# grep -E "n." test1.txt
nice to
nb
[root@localhost ~]# grep -E "n.+" test1.txt          
nice to
nb
[root@localhost ~]# grep -E "n.?" test1.txt
nice to
nb

通过上面,可以看到:
在 aa* 的时候出现了这么多,它的意思是匹配 a 字符后面的任意多个;
在直接 n.+ 的时候并没有出现 n 开头的字符,必须加上 -E 才能显示出;

那么 .+ 和 .? 的区别是什么呢?(可以从grep打印结果的标红字符串中看出区别) 
.+ 是全部匹配出,而 .? 只是匹配出字符 n 后面紧跟的一个字符。

接着看下下来看看 Perl 的正则表达式,grep 需要加-P参数:
.* 的贪婪匹配;
.*? 的惰性匹配。

上面二者之间的区别在于:贪婪匹配是全部匹配到整个字符串,而惰性匹配只是匹配到 tom 这个字符串。

如下示例:通过打印结果中的标红字体就可以看出贪婪匹配和惰性匹配的区别
[root@localhost ~]# grep -P "kevin.*" test2.txt
kevin
kevinisgoodaiyadate
kevinbeijingshangkevin321
xiaoruiskevin
[root@localhost ~]# grep -P "kevin.*?" test2.txt
kevin
kevinisgoodaiyadate
kevinbeijingshangkevin321
xiaoruiskevin


#############  Re正则表达式的几个总结  ###########
\    忽略正则表达式中特殊字符的原有含义 
^    匹配正则表达式的开始行 
$    匹配正则表达式的结束行 
\<   从匹配正则表达式的行开始 
\>   到匹配正则表达式的行结束 
[ ] 单个字符    如[A] 即A符合要求 ,[bB]即b或B符合要求,[abc]即a或b或c符合要求
[ - ] 范围     如[A-Z] 即A,B,C一直到Z都符合要求 
.    有的单个字符 
*    所有字符,长度可以为0 

#######################################################################################################################
#######################################################################################################################
1)grep -f <范本文件> 或 grep --file=<范本文件>   
表示指定范本文件,其内容含有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每列一个范本样式。

简单示例:
下面命令就可以打印出文件test2.txt中与文件test1.txt中的相同行。
[root@localhost ~]# grep -f test1.txt test2.txt
[root@localhost ~]# grep --file test1.txt test2.txt
[root@localhost ~]# grep --file=test1.txt test2.txt
相当于
[root@localhost ~]# cat test1.txt test2.txt|sort|uniq -d

但是要注意一个细节:
grep -f 参数后面作为标准的第一个文件一定不能有空行才行!!!否则打印结果就是最后一个文件的内容!!!!

[root@localhost ~]# cat haha.txt 

123
[root@localhost ~]# cat test.txt 
123
beijing
[root@localhost ~]# grep -f test.txt haha.txt                                          
123
[root@localhost ~]# grep -f haha.txt test.txt     #grep -f后的第一个文件一定不能有空行!否则打印结果就是最后一个文件的全部内容!
123
beijing

2)grep -F 关键字 filename1"  表示将关键字符视为固定字符串的列表。
或者 
"grep -F 关键字符 filename1 filename2 filenamen"   表示会显示出来关键字所在的文件的列表。

[root@localhost ~]# cat test1.txt 
beijing
anhui
shanghai
shenzheng
[root@localhost ~]# cat test2.txt  
beijing
linux
kevin
[root@localhost ~]# grep -F beijing test1.txt         
beijing
[root@localhost ~]# grep -F beijing test1.txt test2.txt 
test1.txt:beijing
test2.txt:beijing

[root@localhost ~]# grep -F "anhui" test1.txt test2.txt 
test1.txt:anhui

#######################################################################################################################
#######################################################################################################################
grep指定查找范围是目录时必用的参数:
grep -r  表示明确要求搜索子目录。等同于 grep -d recurse
grep -d skip  表示忽略子目录

小示例:
遍历当前目录及所有子目录查找匹配"kevin"的行,使用"grep -r"
[root@localhost ~]# grep -r "kevin" .
等同于
[root@localhost ~]# grep -d recurse "kevin" .
 
在当前目录及所有子目录下的txt结尾文件中查找"kevin"
需要注意:命令中*.txt一定要加上引号,表示在当前及其子目录下;如果不加引号,则表示仅仅在当前目录下了!!
[root@localhost ~]# grep -r kevin . --include "*.txt"
等同于
[root@localhost ~]# grep -d recurse kevin . --include "*.txt"

在当前目录下查找包含"kevin"字符的文件,忽略当前目录下的子目录里的文件。
下面命令只会对当前目录下的文件进行查找,当前目录下的子目录里的文件会忽略!
如果不加-d skip, 直接使用grep "kevin" ./* 命令,则结果中会将当前目录的子目录打印出来,报错说子目录是目录而不是文件。如下:
[root@localhost ~]# grep -d skip "kevin" ./*
./register.yml:- hosts: kevin
./test1.txt:kevinboaakevin

[root@localhost ~]# grep "kevin" ./*        
./register.yml:- hosts: kevin
grep: ./test: Is a directory      #将当前目录下的子目录test作为错误提示信息打印出来
./test1.txt:kevinboaakevin

利用 grep 和 find 命令查找文件内容
从根目录开始查找所有扩展名为.log的文本文件,并找出包含 "ERROR" 的行:
[root@localhost ~]# find / -type f -name "*.log" | xargs grep "ERROR"

从当前目录开始查找所有扩展名为.in的文本文件,并找出包含 "kevin_log" 的行:
[root@localhost ~]# find . -name "*.in" | xargs grep "kevin_log"
posted @ 2018-07-12 14:18  散尽浮华  阅读(25543)  评论(1编辑  收藏  举报