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

随笔- 556  文章- 37  评论- 778 

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选项说明

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

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正则表达式元字符集(基本集)

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

^

匹配行的开始 如:'^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次,如:'0\{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 "\"

 

+

匹配一个或多个先前的字符。如:'[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的字符类。

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

[: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引号使用问题

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

单引号:

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

 

双引号:

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

 

单双引号:

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

 

"" 号里面遇到$,\等特殊字符会进行相应的变量替换

'' 号里面的所有字符都保持原样

 

对于字符串,双引号和单引号两者相同, 匹配模式也大致相同, 但有一些区别非常容易混淆, 例如:

grep "$a" file    #引用变量a,查找变量a的值。双引号识别变量。

grep '$a' file    #查找"$a"字符串。单引号不识别变量。

 

grep "\\" file    #grep: Trailing backslash(不知原因)

grep '\\' file    #查找‘\’字符

 

$  美元符

\  反斜杠

`  反引号

" 双引号

这四个字符在双引号中是具有特殊含义的,其他都没有,而单引号使所有字符都失去特殊含义!

 

如果用双引号,查找一个\,就应该用四个\:

grep "\\\\" file 这样就对了,这样等同于:

grep '\\' file

 

第一条命令shell把四个\,转义成2个\传递给grepgrep再把2个\转义成一个\查找;

第二条命令shell没转义,直接把2个\传递给grepgrep再把2个\转义成一个\查找;

其实grep执行的是相同的命令。

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

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

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 '(?

bac

bb

bch

ban

 

按照上面的思路,如果想要取得本机ip地址,可以如下操作:

[root@localhost ~]# ifconfig eth0

eth0: flags=4163  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

        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条件测试。

1

2

3

4

5

6

7

8

9

10

如下是某个脚本中使用的"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同时筛选多个条件                                                                        

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

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 "\" 相当于 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 "\"
或者
# ps -ef|grep "\babc\b"
2)判断该进程的数量是否在3-5之间。
# ps -ef|grep -w abc|wc -l
或者
# ps -ef|grep "\"|wc -l

小示例1

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

写一个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 ']'

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 ']'

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 

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

[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高效搜索用法大全                                                                       

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

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

下面以/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 "\" *.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),找到就显示该行。

如果用egrepgrep -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"

你可能感兴趣的:(Grep 高效用法实战总结 - 运维笔记)