文章目录
- grep基本说明
- grep参数
- 简单示例列举参数
- -v(反选)
- -r -l -H -i(目录子目录、只打印匹配文件、输出文件名、忽略大小写)
- -c -n -o(匹配次数、输出行号、只打印匹配)
- -A -B -C(前后行)
- 正则表达式
- 基本正则表达式与扩展正则表达式
- grep示例
- 附录:正则表达式
- 基本字符
- 特殊字符
- Perl模式正则
grep基本说明
grep是grep、awk、sed这三剑客中最常用的命令了,相对也简单一些。
灵活应用grep能帮我们省很多事,例如很多日志可以直接在服务器查看了,就不用再单独下载下来。
很多日志文件很大,下载慢,文本文件打开也非常慢。所以我们尽量通过grep、awk、sed这三剑客直接在服务器上查看处理了。
grep的基本结构如下:
grep [选项] 匹配模式 file1 file2…
最好的grep文档:
man grep
grep参数
参数 | 说明 |
---|---|
-c | 只统计匹配的行数 |
-v | 反选,排除匹配结果 |
-n | 显示匹配行与行号 |
-i | 不区分大小写 |
-o | 只输出匹配的内容 |
-r | 递归匹配 |
-w | 只匹配单词 |
-x | 匹配整行 |
-l | 小写L,只输出文件名,不输出匹配内容 |
-H | 匹配内容带上文件名 |
-An | 匹配内容的后n行也输出 |
-Bn | 匹配内容的前n行也输出 |
-Cn | 匹配内容的前后n行也输出 |
-E | 使用扩展正则表达式,痛egrep |
-F | 不使用正则表达式,同fgrep |
-P | 使用perl模式正则表达式,和我们平常常用的正则最像 |
-color=auto | 为grep过滤结果添加颜色 |
简单示例列举参数
-v(反选)
-v参数是反选,最常用的就是在ps -ef | grep xxx的时候会把grep本身也打印出来,这时就可以用-v参数过滤掉grep
ps -ef | grep java | grep -v grep
-r -l -H -i(目录子目录、只打印匹配文件、输出文件名、忽略大小写)
-c -n -o(匹配次数、输出行号、只打印匹配)
-A -B -C(前后行)
-A:after 后几行
-B:before前几行
-C:前后几行
正则表达式
要想解锁grep的完全形态,正则表达式肯定少不了。
基本正则表达式与扩展正则表达式
首先我们要区分2个概念,不然容易混乱:
- 基本正则表达式(BRE):grep模式
- 扩展正则表达式(ERE):grep -E、egrep模式
基本正则表达式(BRE)支持元字符:
- .:匹配任意1个字符
- *:匹配前1个字符0次或多次
- ^:行开头
- $:行结尾
- []:可选,如[az]匹配字符a或z
- -:区间,如[a-z]匹配字符a到z
- [^]:反选,如[^0-9]匹配非数字
扩展正则表达式(ERE)基本上和我们平常使用的正则表达式支持的元字符一样。
有一个反直觉的点:
ERE(egrep)中使用反斜杠转义表示普通字符,例如,要匹配?就得使用?
BRE(grep)中使用? 反而变成了正则表达式
之所以有这种情况,是因为grep在识别到?自动转为了egrep模式。
测试文件内容:
ab a. c? [ee] (dd) a* +a+ a|b
11 33 abc22
hello world Luck day
luck boy
44:22:33
long loong looong loop lo?ng
# grep 匹配字符串lo?ng
grep lo?ng grep.txt
# grep 匹配字符串lo?ng
grep "lo?ng" grep.txt# grep 双引号中\?是转义字符,变成正则符号了
grep "lo\?ng" grep.txt# 正则匹配
egrep lo?ng grep.txt
# 正则匹配
egrep lo\?ng grep.txt# egrep 双引号\?被转义,变成普通字符匹配了
egrep "lo\?ng" grep.txt
上面的双引号换成单引号也可以,在引号中\表示转义。
是不是有点乱,所以,为了避免混淆,建议正则直接使用egrep吧。
grep示例
# 查找日志文件中error和warn日志,及其前后5行,忽略大小写
egrep -C5 -i "error|warn" app.log# 统计指定时间段的访问数量
egrep "2024-11-01 06(:[0-9]{2}){2}" access.log | wc -l# 打印8点到10点的日志,根本不用计算时间不要显然思维误区
grep -P '2024-11-01 (08|09|10):\d{2}' app.log
# 打印7点过8分到10分的日志
egrep '2024-10-13 07:(08|09|10)' app.log# 如果是sed,要输出10点日志就不能只到10,因为结束用的是第1个匹配
# sed有一个问题就是 如果灭有匹配到2024-11-01 11:00,就直接干到最后去了
sed -n '/2024-11-01 08:00/,/2024-11-01 11:00/p' app.log
sed -n '/2024-10-13 07:08/,/2024-10-13 07:11/p' app.log# 打印连接的本地ip和远程ip
ss | grep -Po '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
# 打印连接本地ip端口及其对应远程ip端口
ss | grep -Po '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+'
附录:正则表达式
基本字符
元字符 | 含义 |
---|---|
. | 匹配除换行符以外的任何单个字符 |
^ | 锚定到字符串的开始位置 |
$ | 锚定到字符串的结束位置 |
* | 前面的字符匹配零次或多次 |
+ | 前面的字符匹配一次或多次 |
{n} | 前面的字符恰好匹配 n 次 |
{n,} | 前面的字符至少匹配 n 次 |
{,m} | 前面的字符最多匹配 m 次 |
{n,m} | 前面的字符至少匹配 n 次,最多匹配 m 次 |
? | 前面的字符匹配零次或一次 |
() | 分组,允许将多个字符或表达式组合 |
[] | 字符集合,匹配其中的任意一个字符,如[0-9]匹配数字 |
[^] | 排除字符集合,匹配不在括号内的任意一个字符,如[^0-9]匹配非数字字符 |
# 匹配空白字符
egrep [ \t\n\r\f\v] grep.txt# 匹配非空白字符
egrep [^ \t\n\r\f\v] grep.txt# 匹配变量字符
egrep [a-zA-Z_][a-zA-Z0-9_]* grep.txt
特殊字符
表达式 | 含义 |
---|---|
[:alnum:] | 大小写字母数字[a-zA-Z0-9] |
[:lower:] | 小写字母[a-z] |
[:upper] | 大写字母 |
[:alpha:] | 大小写字母[a-zA-Z] |
[:blank:] | space(空格)、tab |
[:cntrl:] | 控制键CR、LF等 |
[:digit:] | 数字[0-9] |
[:graph:] | 非空格键[^:blank:] |
[:print:] | 可打印字符 |
[:punct:] | 标点符号[:";?!'#$^&*()等] |
[:space:] | 空白字符,Tab space CR等 |
[:xdigit:] | 16进制数 |
[:space:]包含:
- 空格(Space):普通的空格字符
- 制表符(Tab):表示一个制表位
- 换行符(NL,New Line):表示文本的一行结束
- 回车符(CR,Carriage Return):在Windows系统中,回车符表示一行的结束
- 垂直制表符(VT,Vertical Tab):用于垂直对齐文本
- 换页符(FF,Form Feed):用于分页
# grep egrep都支持,匹配数字
egrep [[:digit:]] grep.txt
grep [[:digit:]] grep.txt
Perl模式正则
Perl模式更偏向于我们熟悉的模式,更简介一些,除了支持基本字符,还支持下面这些表达式:
表达式 | 描述 |
---|---|
\d | 匹配一个数字的字符,[0-9] |
\D | 非数字,[^0-9] |
\w | 英文字母、数字、下划线,[a-zA-Z0-9_] |
\W | [^a-zA-Z0-9_] |
\s | [\n\t\r\f空格] |
\S | [^\n\t\r\f空格] |
\b | 匹配以英文字母,数字为边界的字符串 |
\B | 匹配不以英文字母,数值为边界的字符串 |
# 匹配数字就不需要使用[[:digit:]]这种了,直接\d就可以
# 注意有\转义,需要用引号包起来
grep -P "\d" grep.txt
grep -P '\d' grep.txt# 提取日志时间
grep -oP '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}' app.log