Linux:grep、sed、awk命令
正则表达式:匹配字符串
sed:擅长文本处理和文件内容替换
grep:擅长搜索信息
awk:擅长处理列数据和替换内容
------------------------------------------------------------------------------------------------------------------------------
正则表达式基本语法:
在线正则表达式测试网址:https://tool.oschina.net/regex/
\bture\b:查找true单词,前后用\b包住
\bHi\b.*\btom\b:查找‘Hi * tom’这个格式的字符串,*表示中间为任意字符
0\d{2}-\d{8}:查找010-12345678格式的电话号码
正则表达式字符 | 意义 |
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\b | 匹配单词的开始或结束 |
\d | 匹配数字 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
* | 重复零次或者更多次前一个字符 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
() | 分组,在后面sed命令的练习中有使用到 |
| | 匹配多个表达式中的任何一个,查找多个表达式,表达式中间用|符号隔开 |
? | 非贪婪匹配 |
练习:
匹配以字符a开头的单词:\ba\w*\b
匹配刚好6个字符的单词:\b\w{6}\b
匹配1个或者更多连续的数字:\d+
匹配5到12位数字:\d{5,12} or ^\d{5,12}$(只匹配数字,防止q11111也能被匹配到)
grep命令:
根据用户指定的规则,对目标文本进行过滤,显示被规则匹配到的行信息,这个规则是支持正则表达式的,因此grep中可以使用正则表达式
命令形式:grep [options] pattern [file]
-v 显示不被匹配规则匹配到的行,相当于反向匹配,默认是显示匹配到的行 |
-i 忽略字符的大小写 |
-n 显示匹配的行号 |
-c 统计匹配的行数 |
-o 仅显示匹配到的字符串 |
-E 使用扩展的正则表达式ERE,相当于egrep |
-r:grep pattern -r dir 递归搜索 |
grep --line-buffered 强制输出结果 |
-A 查看当前查找信息的后面行信息,-A 1代表查看后面一行,-A 2代表查看后面两行,以此类推 -B 查看当前查找信息的前面行信息 -C 查看当前查找信息的上下文,即前面信息和后面的行信息,使用方法同-A |
练习:
grep root 1.txt: 查找1.txt文件中包含root字符的行,并打印在控制台上
grep -o root 1.txt: 查找1.txt文件中包含root字符,但只打印匹配到的root字符串
grep -v root 1.txt: 查找1.txt文件中不包含root字符的行
grep -vn root 1.txt: 查找1.txt文件中不包含root字符的行,并打印出行号
grep ^s 1.txt: 查找1.txt文件中以s字符开头的行
多重管道grep使用时可以使用grep --line-buffered进行强制输出给下一个管道命令使用:
ping 114.114.114.114 | grep --line-buffered 2 |grep 5
grep -A等参数的使用练习:
grep 'root' /etc/passwd
grep -n -A 2 'root' /etc/passwd
如果在pattern中想使用扩展的正则表达式,需要使用-E参数进行扩展,比如查找多个关键字:
grep -E 'root|games' /etc/passwd
sed命令:
sed是流编辑器,一次处理一行内容,sed处理流程:一行存储在模式空间,然后使用sed命令处理,处理完成后显示到屏幕,清空模式,继续导入后面的行循环处理
sed命令和grep类似,但是比grep命令多一些文件操作:增加、删除、修改,命令形式为:
sed [-hn..] [-e<script>] [-f<script file>] [file]
-h 显示帮助 man sed 显示帮助 |
-n 静默模式,仅显示script处理后的结果 |
-e 以指定的script来处理输入的文本文件 【默认为-e,可以省略】 -E 使用扩展的表达式:扩展的正则表达式 |
-f 以指定的script文件来处理输入的文本文件 |
-i 将改动写入源文件 |
a:新增 sed -e '4a newline':在第四行后面新增加一行,内容为newline【-e参数可以省略】 |
c:取代 sed -e '2,5c No 2-5 number':使用No 2-5 number内容去取代2-5行的内容,相当于2-5这四行变成一行内容 |
d:删除 sed -e '2,5d':删除2-5行 |
i:插入 sed -e '2i newline':在第二行前面插入一行,内容为newline |
p:打印 sed -n '/root/p':匹配到两个斜杠里面的内容并打印,两个斜杠之间的内容是支持正则表达式的 |
s:取代 sed -e 's/old/new/g':使用new去替代old,/g表示全局替代,不加g参数的话,每行只会替代第一个匹配到的字符串,如果关键字中包含/那么可以使用@或者#符去替代/,那么就不用使用转义符进行转义了 |
特殊用法的练习:
-i参数的特殊用法:
sed -i.bak 's/abc/ABC' filename -i.bak表示修改源文件之前,将源文件复制一份并命令为filename.bak进行备份保存
分组匹配与字段提取:
echo "12ab34cd" |sed -E 's#([0-9]*)([a-z]*).*#\1 \2#'
解析:具体不懂,大概就是-E支持扩展的表达式,s代表替换,#([0-9]*)([a-z]*).*#\1 \2#三个#号之间,前面两个#号之间匹配到的字符串用后面两个#号的字符替换,同时\1和\2分别表示两个()中的内容吧
这个的高端用法是可以跟bash命令结合一起使用:
ls *.txt|sed -E 's/(.*).txt/\1/'
ls *.txt|sed -E 's/(.*).txt/\1.log/'
awk命令:
awk命令把文件逐行的读入,以空格为默认分割符将每行切片,切开的部分再进行后续处理
处理过程:把行作为输入并赋值给$0变量,这是一个内置变量;然后将行切片,将切片的值从$1($2,$3,...,$n)开始赋值,对行匹配正则/执行动作,打印内容,然后循环导入下一行进行操作
命令形式为:awk 'pattern+action' [file]
-pattern:正则表达式
-action:对匹配到的内容执行的命令(默认为输出每行内容)
常用参数:
awk 'pattern{action}' 命令表达式
awk 'BEGIN{}END{}' 开始和结束
awk '/root/' 正则匹配//之间的内容
awk '/aa/,/bb/' 区间选择
awk '$2~/xxx/' 字段匹配
awk 'NR==2' 取第二行信息
awk 'NR>1' 去掉第一行
fflush() 刷新缓存
BEGIN{FS=':'} 表示指定分隔符为:
$0 代表当前记录
$NF 代表最后一个域
$(NF-1) 代表倒数第二个域
-F 指定字段的分隔符,可以用|指定多个可能的分隔符 -F '<|>',指定了<或者>字符为分隔符
echo "12#34@45%89" |awk -F '#|@|%' '{print $1}'
练习:
多个管道中使用命令,如果时awk命令的话,需要使用到fflush()方法,这样数据才能传给下一个管道命令
ping 114.114.114.114 |awk -F = '{print $4;fflush()}' |grep 7
awk行处理:把单行拆分为多行:echo $PATH|awk 'BEGIN{RS=":"}{print NR,$0}'
awk行处理:把多行组合为单行:echo $PATH|awk 'BEGIN{RS=":"}{print $0}'|awk 'BEGIN{ORS="@@"}{print $0}'
FILENAME awk浏览的文件名 | OFS 输出域分隔符 |
BEGIN 处理文本之前要执行的操作,类似pytest里面的setup | ORS 输出记录分隔符 |
END 处理文本之后要执行的操作,类似pytest里面的teardown | RS 控制记录分隔符,默认为换行符,使用RS可以设置控制记录的分隔符 |
FS 设置输入域的分隔符,等价于命令行的-F选项 | $0 整条记录 |
NF 浏览记录的域的个数(列数) | $1 当前行的第一个域,$2当前行的第二个域,以此类推 |
NR 已读的记录数(行数) |
搜索/etc/passwd有关root关键字的所有行,并显示对应的shell,awk -F : '/root/ {print $7}' /etc/passwd -F : 代表使用冒号来作为输入域的分隔符,而不是使用默认的空格符 /root/:表示查找正则表达式root {print $7}:匹配到合适的行后,打印该行的第七个域内容 |
打印/etc/passwd的第二行信息 ,awk -F : 'NR==2 {print $0}' /etc/passwd NR==2:获取第二行的信息 {print $0}:打印第二行的整条记录 |
使用BEGIN加入标题,awk -F : 'BEGIN{print "BEGIN","BEGIN"}{print $1,$2}' /etc/passwd |
自定义分隔符,echo "123|456|789"|awk 'BEGIN{RS="|"} {print $0}' "123|456|789"这个字符串设置|为分隔符,分隔成了三行 |
ngix日志分析相关命令:
cat:查看文本内容
wc:统计字符、行数、byte自己信息呀啥的。man wc查看帮助 wc -l filename统计行数
sort:排序
uniq:去重
head:查看文件前n行,默认为10行
uniq去重命令练习:增加-c参数可以统计相同数据出现的次数,如果数据不是挨在一起,就不能完全去重
awk '{print $7}' nginx.log |sed -E 's#/topics/[0-9]*#/topics/int#g;s#/replies/[0-9]*#replies/int#g;s#([0-9a-z-]*).png#int.png#g;s#([0-9a-z-]*).jpg#int.jpg#'|sort|uniq -c|sort -nr|head -20