Linux grep
在Linux中,grep是Global search REgular expression and Print out the line(全局搜索正则表达式并打印行)的缩写。顾名思义,grep命令的作用是结合正则表达式模式来匹配文本或者单纯进行简单的文本搜索。
grep工作原理
-
读取数据:可以从标准输入读取数据,也可以从一个或多个文件中读取
-
模式匹配:使用正则表达式(或简单的固定字符串)来对读取到的每行数据进行匹配
-
数据处理:默认会输出所有匹配的行,通过不同的选项,也可以是只输出匹配行的数量或只输出不匹配的行等
-
返回状态码:grep进程执行完成后返回一个状态码(0表示找到匹配,1表示没有匹配,2表示出错)
范例:显示非#号和空格开头的非空行
grep -v '^[[:space:]]*#\|^$' /etc/fstab
# -v:排除,输出不包含指定模式的行
范例:匹配文件中包含指定字符的行
grep "refused" 20231008_error.log
范例:在日志文件中搜索多个文件中的错误代码
grep -f file1 logfile.log
# -f:从一个文件中读取模式,然后使用这些模式去搜索目标文本或文件。
范例:查看apache2的配置文件中,哪些包含了8000这个字符
grep -rl '8000' /etc/apache2/
# -rl搭配:递归检索某个目录文件下的所有文件,只要包含特定内容的,就把文件名显示出来。
# -l:在多个文件中搜索并显示匹配的文件名
# -r:递归地搜索目录,就是把目录下的所有文件都匹配一遍
例如:过滤特定进程,但是不显示grep进程
过滤ssh进程的时候,因为grep进程的参数里面也含有ssh这个参数,所以会将grep进程也给显示出来。
方法一:
ps aux | grep sshd | grep -v grep
方法二:
ps aux | grep [s]shd
原理:
grep默认就支持基本正则表达式,[ ]的意思是取其中一个,且里面是什么,取出来就是什么,例如里面是一个星号(*),取出来还是一个星号,不会被解析为其它意思。在这里的[ ]里面就包含了一个字符s,那么grep会将正则元字符中括号进行解析,最后得到的结果也是ssh。但是grep进程的参数变为了 --color=auto [s]sh 。所以就巧妙将grep进程给过滤掉了。
范例:使用扩展正则表达式
grep默认支持的是基本正则表达式,如果要使用扩展正则表达式的话,还需要加\来转义,太麻烦。直接加 -E 参数就支持扩展正则表达式了。
-
基本正则的5个元字符: ^ $ . [] *
-
扩展正则表达式的5个元字符: + () {} ? |
例如:
grep -Ev '^[[:space:]]*#|^$' /etc/fstab
范例:匹配的时候忽略大小写
当我们要匹配某个字符串的时候,不知道是大写还是小写,就可以直接通过 -i 参数来忽略大小写。
例如:
grep -i hello filename
范例:只输出匹配的部分的内容
默认情况下是将匹配到的一整行全部输出来,通过 -o 参数就可以实现只输出匹配到的内容,而不是输出整行。
例如:
grep -o file_name
范例:匹配到指定内容也不输出
通过-q 选项,grep将不会输出任何内容,但是仍会返回一个状态码。一般在脚本里面使用-q选项。
例如:
if grep -q 'tom' /etc/passwd; then
echo "包含tom用户"
else
echo "不包含tom用户"
fi
说明
1、不管是匹配简单文本还是使用正则表达式,都需要加引号,这样才规范;
2、egrep等价于grep -E,但是更推荐使用grep -E
3、grep默认支持的是基本正则表达式,想要直接使用扩展正则表达式使用egrep或者grep -E
基本使用场景
1、查看指定文本文件中是否包含特定的内容
2、结合管道符将某个进程的标准输出作为grep的标准输入,过滤文本信息
例如:
# 查看指定文本文件中是否包含特定的内容
grep -r "function_name" /path/to/source/code/
# 结合管道符使用
ps aux | grep "nginx"