文章目录
- 一、命令介绍
- 二、grep 的三种形式
- 三、常用选项
- 四、正则表达式
- 五、参考示例
- 在指定的文件中查找指定的关键词
- 查看指定文件中含有特定关键词的文本行
- 查看指定文件中所有包含数字的行
- 在指定的目录下递归搜索指定的字符串,将符合的文本行及其文件名输出
- 在指定文件中搜索指定的字符串,将包含该字符串的行以及后面的指定行数都显示出来
- 将指定文件中含有指定字符串的行及其后面指定数量的行打印输出,且打印每行的字节偏移量
- 在指定的多个文件中搜索指定字符串,并且输出匹配的行及其所属的文件名
- 在指定文件中查找指定字符串,且仅输出匹配到的行数
- 在指定目录及其子目录的所有文件中查找指定字符串,并返回匹配到的文本行内容及对应的文件名
- 只在一级子目录中的特定文件中查找指定的关键词(不在当前目录中的文件查找)
- 查看二级子目录(子目录的子目录)中的特定文件中含有指定关键词的文本行内容
- 查看当前目录及其所有子目录下的文件中含有指定关键词的文本行内容及对应文件名
- 显示指定文件中符合范本样式的文本行内容及对应的行号
- 列出文件内容中含有指定关键词的文件名
- 查看指定文件中含有完整匹配搜索词的匹配项的文本行
- 列出指定目录下的文件中匹配范本样式的字符串及对应的文件名
- 查看指定目录下的文件内容含有符合指定范本样式的字符串的文件名称
- 查看指定目录下的文件内容含有匹配正则表达式字符串的文本行内容和文件名
- 查看指定的目录下除了特定文件之外的文件内容中含有指定关键词的文件名
- 限定在指定文件中进行搜索
- 在指定目录下查找,并且将特定的目录排除在搜索范围之外
- 将指定目录中的所有文件所包含的指定字符串替换成另外一个指定的字符串
 
- 六、grep 和 find 的区别
一、命令介绍
grep 是 Global Search Regular Expression And Print Out The Line 或 Global Regular Expression Print 的简称,意思是全面搜索正则表达式,并将其打印出来。这个命令可以结合正则表达式使用,它也是 Linux 使用最为广泛的命令。
grep 命令的选项用于对搜索过程的补充,而其命令的模式十分灵活,可以是变量、字符串、正则表达式。需要注意的是,一旦模式中包含了空格,务必要用双引号将其引起来。
grep 后面跟着的搜索词可以加上单引号或者双引号,也可以不加任何引号;grep 可以在多种格式的文件中查找指定的内容,例如:json、html、txt、docx 等。
二、grep 的三种形式
Linux 支持三种形式的 grep
- grep:标准 grep 命令
- egrep:简称扩展 grep 命令,其实和- grep -E等价,支持基本和扩展的正则表达式
- fgrep:简称快速 grep 命令,其实和- grep -F等价,不支持正则表达式,按照字符串表面意思进行匹配
三、常用选项
| 选项 | 说明 | 
|---|---|
| -a或--text | 不要忽略二进制数据 | 
| -A <n>或--after-context=<n> | 后面需要跟着具体的文件名,选项后跟着数值,表示除了显示包含符合范本样式字符串的文本行以外,并显示该行之后的 n行内容 | 
| -B<n>或--before-context=<n> | 后面需要跟着具体的文件名,选项后跟着数值,表示除了显示包含符合范本样式字符串的文本行以外,并显示该行之前的 n行内容 | 
| -b<n>或--byte-offset | 后面需要跟着具体的文件名,不仅输出包含指定符合范本样式字符串的行,而且在每行输出之前打印每行基于上一行开始处的字节偏移量 | 
| -c或--count | 后面需要跟着具体的文件名,输出符合范本样式的行数 | 
| -C<n>或--context=<n>或-<n> | 该选项后面必须指定数值,选项 -C和后面的数值可以有无空格;选项--context与后面的数值必须有空格,也可以使用等号=,但是等号与选项和数值之间不允许有空格;选项-与后面的数值之间不允许有空格。除了显示符合范本样式的那一行之外,并显示该行之后n行的内容 | 
| -d <ACTION>或--directories=<ACTION> | 如果输入文件是一个目录,请使用 ACTION 对其进行处理。默认情况下,ACTION 是 read,即读取目录,就像它们是普通文件一样。如果操作是 skip,则自动跳过目录。如果操作是 recurse[ri’kəs],则以递归方式读取每个目录下的所有文件,仅当符号链接位于命令行上时,才跟随符号链接。这相当于 -r选项 | 
| -D <ACTION>或--devices=<ACTION> | 如果输入文件是设备、FIFO 或 socket,请使用 ACTION 对其进行处理。默认情况下,ACTION 是 read,这意味着读取设备就像读取普通文件一样。如果操作是 skip,则设备将被自动跳过 | 
| -e<PATTERN>或--regexp=<PATTERN> | 指定搜索输入时使用的模式:如果输入行与指定的任何模式匹配,则选中该行。当使用多个 -e选项指定多个模式时,或者当模式以破折号-开头时,此选项最有用 | 
| -E或--extended-regexp | 将模式解释为扩展的正则表达式(即强制grep表现为egrep) | 
| -f<范本文件>或--file=<规则文件> | 指定范本文件,其内容有一个或多个范本样式,让 grep 查找符合范本条件的文件内容,格式为每一行的范本样式 | 
| -F或--fixed-regexp | 将模式解释为一组固定字符串(即强制grep作为fgrep) | 
| -G或--basic-regexp | 将模式解释为一个基本的正则表达式(即强制grep像传统的grep那样工作) | 
| -h或--no-filename | 显示含有符合范本样式的字符串的文本行内容,但是不显示该行所属的文件名称,在多文件中查询默认会显示对应的文件名 | 
| -H或--with-filename | 当在指定的多个文件中查找指定的字符串时,不仅将包含指定字符串的行打印输出,同时也输出该行所属的文件名 | 
| -i或--ignore-case | 忽略大小写差异,使大小写不同的字符相互匹配 | 
| -l或--file-with-matches | 列出文件内容含有符合指定范本样式的字符串的文件名称 | 
| -L或--files-without-match | 列出文件内容不含有符合指定范本样式的字符串的文件名称 | 
| -n或--line-number | 显示符合范本样式的文本行内容的同时也在每行前面标示出对应的行号 | 
| -q或--quiet或--silent | 不显示任何信息 | 
| -r或-R或--recursive | 此参数的效果和指定 -d recurse参数相同 | 
| -s或--no-messages | 不显示错误信息 | 
| -v或--revert-match | 从指定文件的内容中查找不匹配指定字符串的行 | 
| -V或--version | 显示版本信息 | 
| -w或--word-regexp | 只选择那些包含构成整个单词的匹配项的行。所谓构成整个单词是指所匹配的子字符串前面必须跟着非单词字符,后面也必须跟着非单词字符。所谓单词字符是指:字母、数字和下划线,其它字符都是非单词字符。如还指定了选项 -x,则此选项无效 | 
| -x或--line-regexp | 只显示整行都匹配指定的范本样式的行 | 
| -y | 此参数效果跟 -i相同 | 
| -o | 只输出文件中匹配到的部分,把文件内容中所有符合范本样式的字符串打印输出 | 
| -m <num>或--max-count=<num> | 找到 num 行结果后停止查找,用来限制匹配行数 | 
四、正则表达式
| 表达式 | 说明 | 
|---|---|
| ^ | 锚(máo)定行的开始 如:’^grep’匹配所有以grep开头的行 | 
| $ | 锚定行的结束 如:‘grep$’ 匹配所有以grep结尾的行 | 
| . | 匹配一个非换行符的字符 如:'gr.p’匹配gr后接一个任意字符,然后是p | 
| * | 匹配零个或多个先前字符如:’*grep’匹配所有一个或多个空格后紧跟grep的行 | 
| .* | 一起用代表任意字符 | 
| [] | 匹配一个指定范围内的字符,如’[Gg]rep’匹配Grep和grep | 
| [^] | 匹配一个不在指定范围内的字符,如:’[^A-FH-Z]rep’匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行 | 
| \(..\) | 标记匹配字符,如’(love)’,love被标记为1 | 
| \< | 锚定单词的开始,如:’<grep’匹配包含以grep开头的单词的行 | 
| \> | 锚定单词的结束,如’grep>'匹配包含以grep结尾的单词的行 | 
| 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 | 单词锁定符,如: '\bgrep\b’只匹配grep | 
五、参考示例
在指定的文件中查找指定的关键词
在文件 /root/test/text.txt 中查找关键词“world”,会输出匹配到的文本行内容:
[root@htlwk0001host ~]# grep world /root/test/text.txt
hello shell world!
shell world
查看指定文件中含有特定关键词的文本行
查看文件 text4.txt 中以 Aug 开始的文本行:
[root@htlwk0001host test1]# grep ^Aug text4.txt
Augfsdf Augfsdfds
注:^ 这是正则表达式的元字符,表示匹配行首。^Aug 表示匹配行首的字符串 Aug
查看指定文件中所有包含数字的行
grep [0-9] /var/log/messages # 选择 '/var/log/messages' 文件中所有包含数字的行 
在指定的目录下递归搜索指定的字符串,将符合的文本行及其文件名输出
查看目录 /var/log 及其所有的子目录中包含字符串"Aug" 的文本行和对应的文件名:
grep Aug -R /var/log/* 
在指定文件中搜索指定的字符串,将包含该字符串的行以及后面的指定行数都显示出来
例如,在文件 /root/test/text.txt 中查找字符串“world”,如果存在则将所在行以及后面的3行打印输出:
[root@htlwk0001host ~]# grep -A 3 'world' /root/test/text.txt
hello shell world! # 该行含有字符串 world,输出此行及其后面的 3 行,但是后面只有 2 行,则输出 2 行
dfdskklllllf
dfsfdsf
shell world # 该行含有字符串 world,输出此行及其后面的 3 行
sdffdsfdsfd
dfsfdfdsfds
fsdfdsfdsfdsf
我们看下文件 /root/test/text.txt 中的实际内容是什么:
[root@htlwk0001host test]# cat text.txt
hello shell world!
dfdskklllllf
dfsfdsf
shell world
sdffdsfdsfd
dfsfdfdsfds
fsdfdsfdsfdsf
fdsfdsfdsfd
选项 -A 和数值之间允许有空格,也允许没有空格:
[root@htlwk0001host ~]# grep -A3 'world' /root/test/text.txt
还可以使用选项 --after-context 查询,不过该选项和数值之间必须有空格,否则会报错:
[root@htlwk0001host ~]# grep --after-context 3 'world' /root/test/text.txt
另外选项 --after-context 还可以使用等号 = 来指定数值,但是等号 = 左右两端不可以有空格:
[root@htlwk0001host ~]# grep --after-context=3 'world' /root/test/text.txt
将指定文件中含有指定字符串的行及其后面指定数量的行打印输出,且打印每行的字节偏移量
将文件 /root/test/text.txt 中含有字符串“world”的行及其后面的 3 行打印输出,且打印每行的字节偏移量:
[root@htlwk0001host ~]# grep -b3 'world' /root/test/text.txt # 选项 -b 和数值之间不可以有空格
0:hello shell world!
19-dfdskklllllf # 该行的第 1 个字符 d 正好是前面一行从 h 开始数起的第 19 个字符
32-dfsfdsf # 该行的第 1 个字符 d 也正好是前面一行从 d 开始数起的第 13 位,那么加上前面一行 d 的偏移量 19,就是 32 
40:shell world # 该行的第 1 个字符 s 是前面一行从 d 开始数起的第 8 位,那么加上前面一行 d 的偏移量 32,就是 40
52-sdffdsfdsfd
64-dfsfdfdsfds
76-fsdfdsfdsfdsf
选项 -b 后面不跟着数值,则只打印包含指定字符串的行及其字节偏移量:
[root@htlwk0001host ~]# grep -b 'world' /root/test/text.txt
0:hello shell world!
40:shell world
还可以使用选项 --byte-offset,但是该选项后面不可以跟着数值:
[root@htlwk0001host ~]# grep --byte-offset 'world' /root/test/text.txt
0:hello shell world!
40:shell world
还可以指定多个文件进行查找:
[root@htlwk0001host test]# grep -b3 'world' text.txt text1.txt
text.txt:0:hello shell world!
text.txt-19-dfdskklllllf
text.txt-32-dfsfdsf
text.txt:40:shell world
text.txt-52-sdffdsfdsfd
text.txt-64-dfsfdfdsfds
text.txt-76-fsdfdsfdsfdsf
--
text1.txt:0:dsfdsaljflvoworlddslfljds324432
text1.txt-32-sfdsgdflfmbndfkjgrut3409t8ierrig
text1.txt:65:gkldfjgleoeworldsdlfjdlsworld
text1.txt-95-dsfdsfdsf
text1.txt-105-fdsfdsfdsfdsfdsfsdfsdfsdf
text1.txt-131-dsfsdfdsfsddfgdfgdfgdfgewreeortreoitureoimbn
在指定的多个文件中搜索指定字符串,并且输出匹配的行及其所属的文件名
[root@htlwk0001host ~]# grep -H 'world' /root/test/text.txt /root/test/text2.txt
/root/test/text.txt:hello shell world!
/root/test/text.txt:shell world
以上结果显示,匹配到两行文本,且这两行内容都是在文件 /root/test/text.txt 中。
在指定文件中查找指定字符串,且仅输出匹配到的行数
[root@htlwk0001host test]# grep -c 'world' text.txt text1.txt
text.txt:2 # 文件 text.txt 匹配到 2 行
text1.txt:2 # 文件 text1.txt 也匹配到 2 行
在指定目录及其子目录的所有文件中查找指定字符串,并返回匹配到的文本行内容及对应的文件名
[root@htlwk0001host test]# grep 'world' -d recurse ./
./text.txt:hello shell world!
./text.txt:shell world
./tf_company_20210603.sql:Bigworld引擎的游戏开发技术。整个团队的核心成员均来自国内顶尖游戏研发公司,并全部拥有两个以上完整大型MMORPG项目的开发及运营经验。作为拥有国内创业公司中最强开发实力的第四代互联网企业,境界公司旨在为用户创造精致有趣,丰富平衡的3D游戏世界。 公司网址 www.363.com', 0.00, 0, 0, 0, 0.0000, '2021-02-17 14:34:47', '2021-02-17 14:34:47', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
./tf_company_20210603.sql:3, 4, 1, NULL, '无忧互通(www.sail2world.com),是一家专注于提供最领先的移动游戏和互联网娱乐产品的研发商和运营商。
./tf_company_20210603.sql:the world, with 45'2021-02-26 14:47:21', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
./text1.txt:dsfdsaljflvoworlddslfljds324432
./text1.txt:gkldfjgleoeworldsdlfjdlsworld[root@htlwk0001host ~]# grep 'make' -d recurse ./test
./test/text.html:<p class="p1">ffdsfsmakefdsfsdfmake</p>
./test/text.html:<p class="p1">sdfsdfdsmake</p>
./test/text.docx:fsdfdsmakesdfsdfsdfds
./test/text.docx:makedsfsdfdsfd
./test/text.txt:Sdfsd make love3434sdfdsfs
./test/text.txt:Fdsfgmake dsfsdf;dgdfdf
./test/text.txt:Make ldsfdsfmake lovefsdf343dv.,.,,.fdsfdsf
./test/text.json:make lovesdlfjf23423432dsffdsf
./test/text.json:sdfldjlfksjff makefsfddsfdsdsf24234ewdfd
./test/text.json:sfdmakesdfdsfds
注:选项 -d 后面必须跟着操作项(read/skip/recurse)和目录,但是其它两种 ACTION 在实际业务中比较少使用,另外操作项 read 非常奇怪,你指定了 read,后面反而不能跟着目录,必须跟着文件
只在一级子目录中的特定文件中查找指定的关键词(不在当前目录中的文件查找)
[root@htlwk0001host ~]# grep 'make' */*.docx
make23434354
注:第一个 * 表示一级子目录,第二个 * 表示匹配以 docx 为扩展名的任意文件名
查看二级子目录(子目录的子目录)中的特定文件中含有指定关键词的文本行内容
[root@htlwk0001host ~]# grep 'make' */*/*.docx
fsdfdsmakesdfsdfsdfds
makedsfsdfdsfd
注:只在二级子目录下的文件中查找,不会在当前目录、一级子目录及二级子目录下的所有子目录中查找
查看当前目录及其所有子目录下的文件中含有指定关键词的文本行内容及对应文件名
在当前目录及其所有子目录中的文件查找字符串“make”,命令如下:
lwxdeMacBook-Air:test lwx$ grep make -r .
./text.html:<p class="p1">ffdsfsmakefdsfsdfmake</p>
./text.html:<p class="p1">sdfsdfdsmake</p>
./test1/text1.txt:make lovesdfsdfd23423
./text.docx:fsdfdsmakesdfsdfsdfds
./text.docx:makedsfsdfdsfd
./text.txt:Sdfsd make love3434sdfdsfs
./text.txt:Fdsfgmake dsfsdf;dgdfdf
./text.txt:Make ldsfdsfmake lovefsdf343dv.,.,,.fdsfdsf
./text.json:make lovesdlfjf23423432dsffdsf
./text.json:sdfldjlfksjff makefsfddsfdsdsf24234ewdfd
./text.json:sfdmakesdfdsfds
注:选项 -r 表示递归,搜索关键词可以不加引号。
显示指定文件中符合范本样式的文本行内容及对应的行号
[root@htlwk0001host ~]# grep -n 'world' /root/test/text.txt
1:hello shell world!
4:shell world
列出文件内容中含有指定关键词的文件名
将当前目录及其所有子目录中的文件内容中含有字符串“make”的文件名打印输出:
liaowenxiongdeMacBook-Air:test liaowenxiong$ grep make -r . | cut -d: -f1 | uniq
./text.html
./test1/text1.txt
./text.docx
./text.txt
./text.json
注:cut 是字符串分割命令,-d 用来定义分割符号,-d: 表示将冒号 : 定义为分隔符,-f 显示指定字段的内容,-f1 表示显示第 1 个字段的内容。所以像这样的字符串“./text.docx:makedsfsdfdsfd”,会被分割成“./text.docx”和“makedsfsdfdsfd”,显示第 1 个字段的内容就是“./text.docx”,因为同个文件中有多行匹配到指定的关键词,所以分割和取第 1 个字段的内容后会存在重复的数据,那么把命令 cut 处理后的数据再输出给命令 uniq 进行去重后就得到上述的结果了。
查看指定文件中含有完整匹配搜索词的匹配项的文本行
如下图所示:
 
 注:所谓完整匹配范本样式,是指匹配项不仅仅内容匹配,而且匹配项的前后必须跟着非单词字符才行。例如,上图中的字符串“worldworl”的确含有搜索词“world”,但是后面跟着单词字符 w,所以不满足要求。
列出指定目录下的文件中匹配范本样式的字符串及对应的文件名
在把文件内容中所有符合范本样式的字符串打印输出
 在当前目录及其所有的子目录下的文件中查找关键词“world”,并将匹配到的字符串打印输出:
[root@htlwk0001host test]# grep world -o -r .
./text.txt:world
./text.txt:world
./text.txt:world
./text.txt:world
./text.txt:world
./text.txt:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./tf_company_20210603.sql:world
./test1/text4.txt:world
./text1.txt:world
./text1.txt:world
./text1.txt:world
查看指定目录下的文件内容含有符合指定范本样式的字符串的文件名称
查看当前目录及其子目录中的内容含有指定关键词“world”的文件名:
[root@htlwk0001host test]# grep world -l -r .
./text.txt
./tf_company_20210603.sql
./test1/text4.txt
./text1.txt
注:-l 表示查看内容匹配 pattern 的文件名;-r 表示对指定的目录递归处理。
查看指定目录下的文件内容含有匹配正则表达式字符串的文本行内容和文件名
[root@htlwk0001host test]# grep '[^a-z]oo' -n -r .
./text.txt:5:worldeeworld.'oo  
./text.txt:6:sdf33oofdsfdsfd
./text.txt:8:dfsfdfdsfds=oo
注:-n 表示输出对应的行号,正则表达式可以加单引号或者双引号,也可以不加引号。
查看指定的目录下除了特定文件之外的文件内容中含有指定关键词的文件名
列出目录 /etc 及其所有子目录下的文件内容含有关键词“bash”的文件名,但是以 .conf 为后缀名的文件不在搜索范围之内:
grep -Ril --exclude=*.conf bash /etc/*
注:--exclude 用来指定被排除的文件
限定在指定文件中进行搜索
只在目录 /etc 及其子目录下的配置文件(扩展名为 .conf)中搜索指定的字符串“bash”,并将匹配到的文件名输出:
grep -Ril --include=*.conf bash /etc/*
在指定目录下查找,并且将特定的目录排除在搜索范围之外
查看 /etc 及其子目录中的内容包含完整匹配字符串 stretch 的匹配项的文件名,但不包括 /etc/grub.d 目录下的文件:
# grep --exclude-dir=/etc/grub.d -Rwl stretch /etc/*
/etc/apt/sources.list
/etc/dictionaries-common/words
/etc/os-release
将指定目录中的所有文件所包含的指定字符串替换成另外一个指定的字符串
将当前目录及其所有子目录中的所有文件内容中的关键词“aliyun” 替换成“lwx”:
[cqs@centos7]$ sed  -i "s/aliyun/lwx/g" `grep -rl aliyun ./`
注:后面的 grep 命令语句必须放在反撇号之内,这样才会执行该命令语句
六、grep 和 find 的区别
grep 是查找文本内容,所以指定文件时则会进入文件内容中查找,而 find 是查找文件名,无法查找文件的内容