linux系统——shell编程文本处理三剑客
#6 - 文本处理三剑客:
- grep
- sed
- awk
- grep —— 过滤,查找文本中的内容:
- 分类:
1,grep
2,egrep —— 支持正则表达式
3,fgrep —— 就不支持正则表达式 - 参数:
1,grep -q —— 静默,查找到也没有输出
2,grep -v —— 取反,输出匹配到的以外的内容
3,grep -R —— 可以查目录下的文件
3,grep -o —— 只输出匹配到的关键字
4,grep -B2 —— 输出匹配到的那行的前两行
5,grep -A2 —— 输出后两行
6,grep -C2 —— 输出前后两行
7,egrep -l —— 只输出文件名
8,egrep -n —— 带行号输出 - 示例:
egrep 'nw' abc.txt \\abc中查找nw
egrep 'nw' a*.txt \\a开头的文件中查找nw
egrep '^n' abc.txt \\abc中查找n开头的
egrep '4$' abc.txt \\abc中查找4结尾的
egrep tb ac abc.txxt \\在ac,abc两个文件中查找tb
egrep 'tb ac' abc.txt \\在abc文件中查找tb和ac
egrep '5\..' abc.txt \\在abc中查找5.+任一字符
egrep '^[we]' abc.txt \\在abc中查找w或e开头的
egrep 'ss*' abc.txt \\在abc中查找1-多个s连接的
egrep '3+' abc.txt \\在abc中查找1-多个3连接的
egrep '2\.?[0-9]' abc.txt \\在abc中查找2 + 0-多个点 + 0-9任一数字
egrep 's(h|u)' abc.txt \\在abc中找sh或su
egrep 'sh|u' abc.txt \\在abc中找sh或u
- sed —— 流编辑器,免交互:
-
格式:
sed 选项 命令 文件 (多是用这个)
sed 选项 -f 脚本 文件 -
sed和正则:
sed -r -r选项支持正则表达式
sed -i 操作写入文件 -
命令:
1,删除:d —— delete
2,替换:s
3,读文件:r —— read
4,写文件:w —— write
5,追加:a —— after(加到匹配行之后)
6,插入:i —— insert(插到匹配行之前)
7,替换整行:c —— change
8,获取下一行:n —— next(多和其他命令组合使用)
9,反向选择:!—— 取反
10,多重编辑 e —— 多条命令组合时 加-e
11,& —— 找到什么调用什么 -
示例:
1,删除:d
sed -r '/root/d' passwd \\删除匹配到root的行
sed -r '3d' passwd \\删除第三行
sed -r '3{d}' passwd \\删除第三行
sed -r '3{d;}' passwd \\删除第三行后执行其他操作
sed -r '3,$ d' passwd \\删除第三到最后行
sed -r '$ d' passwd \\删除最后一行
2,替换:s
sed -r 's/root/aofa/' passwd \\匹配到每行第一个root替换成aofa
sed -r 's/root/aofa/g' passwd \\全局替换
sed -r 's/[0-9][0-9]$/&.5/g' passwd \\全局替换,结尾两个数字替换成这两个数字加.5
3,读文件:r
sed -r '$r 1.txt' passwd \\最后一行增加1.txt文件内容
sed -r '/root/r 1.txt' passwd \\匹配到root后在那行后增加1.txt内容
4,写文件:w
sed -r 'w 111.txt' passwd \\passwd文件内容全部写到111
sed -r '/root/w 111.txt' passwd \\匹配到root后将那行写到111
sed -r '1,5w 111.txt' passwd \\将passwd文件1-5行写到111
5,追加:a
sed -r 'a123' passwd \\在每一行后加上123
sed -r '2a123' passwd \\在第二行后加上123
sed -r '2a 111\
>222\
>333' passwd \\在第二行后增加三行,\是转意回车换行
6,插入:i
sed -r '2iaaa' passwd \\在第二行前增加一行aaa
sed -r '2i aaa\
>bbb\
>ccc' passwd \\在第二行前增加三行
7,替换整行:c
sed -r '2caaaaaa' \\第二行整行替换成aaaaaa
sed -r '2c aaa\
>bbb\
>ccc' passwd \\第二行替换成三行
8,获取下一行:n
sed -r '/root/{n;d}' passwd \\匹配到root后删除root行的下一行
sed -r '/root/{n;s/bin/ding/g}' passwd \\匹配到root后,将下一行的bin换成ding
9,反向选择:!
反向选择,选择的是命令作用范围
sed -r '2,$d' passwd \\删除第二行到最后
sed -r '2,$!d' passwd \\删除开始到第一行
10,多重编辑:e
sed -r -e '1,3d' -e '4s/adm/adming' passwd
\\同时进行多个操作,先删除1-3行,再将原第四行的adm换成adming
- awk —— 对文本的列操作(切片):
-
语法:
awk [options] ‘commands’ filename
[options] :
例如-F —— 定义切割符commands:
BEGIN{} —— 行处理前
{} ——— 行处理时
END{} —— 行处理后 -
内部变量:
1,FS —— 输入字段分隔符(默认空格)
awk -F: '{print $1, $3}' /etc/passwd | head -1
root 0
或
awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd | head -1
root x 0
或
awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd | head -1
root 0
2,OFS —— 输出字段分隔符(默认空格)
awk -F: '{print $1,$2,$3,$4}' /etc/passwd | head -1
root x 0 0
awk -F: 'BEGIN{FS=":";OFS="+++"}{print $1,$2,$3,$4}' /etc/passwd | head -1
root+++x+++0+++0
3,RS —— 输入记录(行)分隔符(默认换行符)
awk '{print $0}' a.txt
111 222 333 444 555:666:777
awk 'BEGIN{RS=" "}{print $0}' a.txt
111
222
333
444
555:666:777
4,ORS —— 输出记录(行)分隔符(默认换行符)
5,NR —— 多文件汇总编号
awk -F: '{print NR, $0}' /etc/centos-release /etc/hosts
1 CentOS Linux release 7.3.1611 (Core)
2 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
3 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
6,FNR —— 多文件独立编号
awk -F: '{print FNR, $0}' /etc/centos-release /etc/hosts
1 CentOS Linux release 7.3.1611 (Core)
1 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
2 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
7,NF —— 字段总数(文件有几列NF,值就是几)
awk -F: '{print NF, $0}' /etc/passwd
7 root:x:0:0:root:/root:/bin/bash
7 bin:x:1:1:bin:/bin:/sbin/nologin
7 daemon:x:2:2:daemon:/sbin:/sbin/nologin
awk -F: '{print NF, $NF}' /etc/passwd
7 /bin/bash
7 /sbin/nologin
7 /sbin/nologin
- 格式化输出:print 函数
date |awk '{print "Month: " $2 "\nYear: " $1}'
Month: 11月
Year: 2017年
awk -F: '{print "username is: " $1 "\t uid is: " $3}' /etc/passwd | head -1
username is: root uid is: 0
awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd | head -1
username and uid: root 0!
- 模式(正则表达式)及动作:
1,字符串比较:
awk '/^root/' /etc/passwd
awk '$0 ~ /^root/' /etc/passwd \\~ 像,全局匹配开头像root,输出那行
awk '$0!~/^root/' /etc/passwd
awk -F: '$1 ~ /^root/' /etc/passwd \\:为分隔符,匹配开头像root,输出整行
2,数值比较:
关系运算:
awk -F: '$3 == 0' /etc/passwd \\匹配第三列等于0,输出那行
awk -F: '$3 == 1' /etc/passwd
awk -F: '$3 < 10' /etc/passwd \\匹配第三列小于10,输出那些行
== 也可以用于字符串判断
awk -F: '$7 == "/bin/bash"' /etc/passwd
awk -F: '$1 == "alice"' /etc/passwd \\匹配第一列是alice,输出那行
逻辑运算:
awk -F: '$3 * 10 > 500' /etc/passwd
\\匹配第三列的值*10后大于500的列,输出那些列的行
3,多条件:
逻辑操作符:
awk -F: '$1~/root/ && $3<=15' /etc/passwd
\\匹配第一列像root并且第三列小于等于15的,输出那行
awk -F: '$1~/root/ || $3<=15' /etc/passwd
\\匹配第一列像root或者第三列小于等于15的,输出那些行
awk -F: '!($1~/root/ || $3<=15)' /etc/passwd
\\输出除去匹配第一列像root或第三列小于等于15的那些行,!取反
范围模式:
语法:
awk '/从哪里/,/到哪里/' filename
示例:
awk -F: '/adm/,/lpd/' /etc/passwd
从adm到ldp,显示出来,注意避免匹配重复的字段。
- awk 脚本编程:
1,awk调用变量:
自定义内部变量 -v
awk -v user=root -F: '$1 == user' /etc/passwd
-v定义变量
外部变量 " "
[root@localhost ~]# heihei=shutdown
[root@localhost ~]# echo $heihei
shutdown
[root@localhost ~]# awk -F: '$1 ~ "'"$heihei"'" ' passwd
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
注意使用单引号时,内部需要用双引转义
2,条件及判断:
if 单分支:
格式:
{if(表达式){语句;语句;...}}
需求:
如果$3是0,就说他是管理员
示例:
awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
if 双分支:
格式:
{if(表达式){语句;语句;...}else{语句;语句;...}}
需求:
统计管理员和系统用户数量
示例:
awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数: "count ; print "系统用户数: "i}' /etc/passwd
if 多分支:
句式:
1,{if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}
2,if (条件){动作}elseif(条件){动作}else{动作}
3,if(){}else if (){}else if(){}else{}
示例一:
需求:显示出三种用户的信息
管理员:管理员ID为0
内置用户:用户ID<1000
普通用户: 用户ID>999
awk -F: '{if($3==0){print $1," is admin "}else if ($3>999){print $1," is user"}else {print $1, " is sofo user"}}' /etc/passwd
示例二:
需求:统计出三种用户的数量
管理员数量:管理员ID为0
内置用户数量:用户ID<1000
普通用户数量: 用户ID>999
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
或:
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数: "i; print "普通用个数: "k; print "系统用户: "j}' /etc/passwd