一、概述
grep 在一个或多个输入文件中搜索包含与指定模式匹配的行。默认情况下,grep匹配输出的行。
二、运行
[root@hecs-394374 ~]# grep 'echo' function8.sh
echo "The sum is: $sum"
三、命令行参数
(1)--help
打印一条用法信息,简要总结命令行选项和错误报告地址。
(2)-V
也可以写成 --version 获取版本号信息
四、匹配模式
(1)-G
--basic-regexp 将模式解释为基本正则表达式(默认)
上栗子🌰~
# 在该文件中查询1-9区间的数字
[root@hecs-394374 ~]# grep '[1-9]' function8.sh
for ((i=1; i<=100; i++))
[root@hecs-394374 ~]#
(2)-E
--extended-regexp 将模式解释为扩展正则表达式(EREs)。(-E由POSIX指定。)
如果你写了一个正则表达式匹配不到结果的时候,你就前面加个 -E 去扩展正则表达式。
(3)-F
--fixed-strings 将模式解释为固定的字符串,而不是正则表达式。
上栗子🌰~ 不加-F, .默认就是单个字符。加了-F,就是单纯想要找“点号”。
[root@hecs-394374 ~]# grep '.' function8.sh
#!/bin/bash
sum=0
for ((i=1; i<=100; i++))
do
((sum += i))
done
echo "The sum is: $sum"
..
...
....
[root@hecs-394374 ~]# grep -F '.' function8.sh
..
...
....
[root@hecs-394374 ~]#
(4)-P
--perl-regexp
将模式解释为perl兼容的正则表达式,perl也是一种语言。
下面栗子看不出来效果,我们直接上效果图~ -P 可以把 \d 解析为数字。
[root@hecs-394374 ~]# tail function8.sh
sum=0
for ((i=1; i<=100; i++))
do
((sum += i))
done
echo "The sum is: $sum"
..
...
....
[root@hecs-394374 ~]# grep '\d' function8.sh
do
done
[root@hecs-394374 ~]# grep -P '\d' function8.sh
sum=0
for ((i=1; i<=100; i++))
[root@hecs-394374 ~]#
(5)那grep,fgrep和egrep代表什么?
grep这个名字来自于在Unix上行编辑的方式。
fgrep等价于 grep -f,egrep等价于grep -e ,其实是快捷命令
fgrep表示固定模式。egrep表示扩展模式。
五、匹配控制
(1)-e 匹配一个或者多个模式,是“or”的关系
因为正常我们找一个,所以-e可以省略掉,如果我们找多个呢,那该怎么写呢?
[root@hecs-394374 ~]# grep '.' function8.sh
#!/bin/bash
sum=0
for ((i=1; i<=100; i++))
do
((sum += i))
done
echo "The sum is: $sum"
..
...
....
[root@hecs-394374 ~]# grep -e 'i' -e 'echo' function8.sh
#!/bin/bash
for ((i=1; i<=100; i++))
((sum += i))
echo "The sum is: $sum"
下面栗子🌰看不出来效果,我们直接上效果图~
(2)-f file 从文件中获取模式。
如果匹配模式有很多,可以考虑放在一个文件里面。
echo 'i' > patterns 将i重定向到patterns文件里
grep -f patterns function8.sh 从patterns文件中读取匹配模式,然后再从funciton8.sh中去匹配
当然了patterns里面可以放多个匹配模式。
我追加‘ec’放入patterns文件里。
(3)-i 忽略大小写
(4)-y 忽略大小写
(5)-v 反转匹配的意义,以选择不匹配的行
下面的demo可以看出来,没有选择有‘echo’的这一行。
(6)-w 全词匹配 匹配一个单词,而不是拿单词的一部分
(7)-x 只选择那些完全匹配整行的匹配项
整个行匹配了才会输出这个行
六、通用输出控制
(1)-c
完整写法 --count,抑制正常输出:
打印每个输入文件匹配了多少行。
也可以后面跟2个文件名
(2)--color
修改展示在终端上的字体演示演示 ,这个大家想了解就自行bd查阅资料叭~
(3)-L
等价于--files-without-match,抑制正常输出,打印那些没有匹配的输入文件的名称。
首先我们先看下grep hello *.*, 查看当前目录里所有文件里匹配的行
grep -L hello *.* ,打印不匹配hello的文件名
(4)-l
等价于--files-with-matches,打印哪些能匹配到的文件名
(5)-m
--max-count
指定最大匹配行数
我能匹配到3行,但是我只想匹配两行
(6)-o
--only-matching,只打印匹配行的匹配(非空)部分,每个这样的部分在单独的输出行上。
(7)-q
--quiet
--silent
安静的;不要向标准输出写入任何内容。如果找到任何匹配,立即退出,状态为零,即使检测到错误。匹配到是0 没匹配到是1.
七、输出行上下文控制
上下文行是在匹配行附近的不匹配行。他们只有在使用以下选项之一时才会输出。无论如何设置这些选项,grep都不会多次输出任何给定行。如果指定了-o(--only-matching)选项,这些选项将不起作用,并在使用时给出警告
(1)-A
--after-context
在匹配的行之后打印尾随上下文的num行
匹配到行之后,把匹配到行后面2行也打印出来。
(2)-B
--before-context,匹配到行之后,连同把匹配的行的前2行也打印出来。
(3)-C
-C num
-num
--context num
输出匹配行的前面x行和匹配行的后面x行
(4)--group-separator=xxxx
我后面跟了2个文件,打印出来的结果中间是用“--”隔开,那我想用其他符号比如说星号代替咋办?
可以这么玩
grep -C 2 hello --group-separator=**** res1.txt res1.txt
那如果我不想给它加上分隔符怎么办?
grep -C 2 hello --no-group-separator res1.txt res1.txt
(5)-r
--recursive,递归地读取和处理目录中的所有文件。遵循命令行上的符号链接,但跳过递归遇到的符号链接(软链接)。
简单来说就是可以从你写的目录中的所有文件去挨个查找匹配行。
八、案例
(1)如何只列出匹配文件的名称? -l
-l ,只列出匹配行相关的文件的名称。
-L ,只列出匹配行无关的文件的名称。
Demo:比如说我这个aa目录下面,有哪些文件能匹配hello?
答案:
grep -l -r hello aa
(2)如何递归的搜索目录? -r
那如果模式或者文件的前导是‘-’,该怎么办?
还是按之前 grep '--cut here--' 文件名, 行得通吗?很明显不行。
那怎么做呢,我们只需要在前面加个 -- 就好了。
或者,可以使用 -e 表示模式和以 ./ 开头的文件名,以防止对‘-’开头的错误理解。
(3)假设我想搜索整个单词,而不是单词的一部分? -w
当我 grep -w 'worl' test.txt 的时候,查不到匹配行,是因为我想搜索整个单词,而非单词的一部分,所以下面当我查world的时候就能查出来匹配行了。
(4)如何输出上下文周围的匹配行? -A 或者 -B 或者 -C
-A ,匹配行后面几行
-B,匹配行前面几行
-C,匹配行前后各几行
(5)如何强制grep打印文件名?
grep hello res1.txt 默认是不会打印文件名的。
grep hello res1.txt res1.txt 后面跟2个文件名才会打印文件名。
可以后面跟个文件名,再加上 /dev/null 会强制grep打印文件名。
(6)查找某一个进程的id是多少?
比如说我想查找关于docker进程id是多少?
这个其实是一个grep的进程,那这个时候我不想显示这个grep的进程怎么办呢?
ps -ef | grep [d]ocker
这个时候就不会显示这个grep的进程
或者我只想查找看9月份的文件怎么看呢?
ls -l | grep Sep
(7)为什么grep报告“Binary file matches”?
(8)为什么‘grep -lv’不打印不匹配的文件名?
grep -L 打印不匹配行的文件名。
(9)我可以用‘|’做‘or’,但是用‘and’怎么办?
grep -e 'a' -e 'if' test , 查找a或者if的行
grep -e 'a' test.sh | grep -e 'if' , 查找既有a又有if的行 (先筛选有a的匹配行,再去筛选有if的匹配行)
(10)如何同时在标准输入和文件中搜索?
使用特殊的文件名'-':
cat /etc/passwd | grep 'alain' - /etc/motd