Grep 高效用法实战总结 - 运维笔记
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,能使用正则表达式搜索文本,并把匹配的行打印出来。grep主要作用是过滤出指定的行,指定的行满足什么条件,满足的条件可配合正则表达式来表示,实现强大的文本处理。
文本处理工具分类
常用的有:grep,egrep,fgrep。
三者区别
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"