1、常用的选项
-n:静默输出,关闭模式空间的输出,一般与p一起用
-e:允许进行多项编辑,也就是说对同一行做多次处理、也可以做多点编辑
-e ‘动作‘ -e ‘动作‘ 等价于 ‘动作1;动作2‘
-f sed脚本 : 指定运行的sed脚本的
-r:允许使用扩展正则
-i:直接修改原文件
2、Address : 定址、地址
1)单独的行号
如: 1 就表示要处理第一行
$ 表示最后一行
2)起始行,结束行
如: 1,5 处理第一行到第五行
3)/正则表达式/
如:/^root/ 处理以root开头的行
4)/正则表达式1/,/正则表达式2/ 最小匹配
表示处理从匹配到正则表达式1的行开始,到第一次匹配到正则表达式2之间的所有行
如果正则表达式1匹配到了,正则表达式2未匹配到,那么就从匹配到正则表达式1的行开始,一直处理到文件结束
如果正则表达式1未匹配到,那么就不对文件做处理。
如:/^bin/,/bash$/
binsdadaddaddass
dsfasidsfdhfj09bash
dasdasdasdf--bash
5)起始位置,+N 不是特别常用
表示从起始位置开始,后面的N行都处理
如:3,+5 处理3-8行
3、Command
常用的:d p s y q
其他的:a c i r w
h H g G
1)d:删除
~# sed ‘/UUID/d‘ /etc/fstab
~# sed ‘1,5d‘ /etc/fstab
~# sed ‘$d‘ /etc/fstab
~# sed ‘/tmp/,/sfs/d‘ /etc/fstab
~# sed ‘/UUID/,+5d‘ /etc/fstab
删除从第5行开始到最后一行的所有内容
~# sed ‘5,$d‘ /etc/passwd
2)p:打印
~# cat -n /etc/passwd | head > pass
~# sed ‘p‘ pass //每行会打印两遍,一遍是处理结果,一遍是模式空间的输出
~# sed -n ‘p‘ pass //只会打印一遍,因为模式空间的输出被关闭了
~# sed -n ‘3,5p‘ pass // 打印文件的3到5行
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
~# sed -n ‘3p‘ pass
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
! 非
~# sed ‘3!d‘ pass //等价于打印第3行
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
练习:
用sed分别实现head -1 和 tail -1的功能
head -1
~# sed -n ‘1p‘ pass
1root:x:0:0:root:/root:/bin/bash
~# sed ‘1!d‘ pass
1root:x:0:0:root:/root:/bin/bash
tail -1
~# sed -n ‘$p‘ pass
10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
~# sed ‘$!d‘ pass
10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
3)r 读取
~# sed ‘/^root/r /etc/issue‘ /etc/passwd
1root:x:0:0:root:/root:/bin/bash
Red Hat Enterprise Linux Server release 6.4 (Santiago)
Kernel \r on an \m
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6sync:x:5:0:sync:/sbin:/bin/sync
7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8halt:x:7:0:halt:/sbin:/sbin/halt
9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
4)w 写
~# sed ‘/root/w /tmp/douni‘ pass //将匹配到的行另存到文件中
~# cat /tmp/douni
1root:x:0:0:root:/root:/bin/bash
5)a 追加 在匹配到的行的下一行插入内容
~# sed ‘/root/a hello root‘ pass | head -5
1root:x:0:0:root:/root:/bin/bash
hello root
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
在文件的最后一行插入新内容
~# sed ‘$a The End‘ pass
1root:x:0:0:root:/root:/bin/bash
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6sync:x:5:0:sync:/sbin:/bin/sync
7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8halt:x:7:0:halt:/sbin:/sbin/halt
9mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
The End
6)i 插入 在匹配行的上一行插入内容
~# sed ‘/daemon/i SO COOL‘ pass | head -5
1root:x:0:0:root:/root:/bin/bash
2bin:x:1:1:bin:/bin:/sbin/nologin
SO COOL
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
~# sed ‘1i BEGINNING‘ pass | head -5 //在第一行插入内容
BEGINNING
1root:x:0:0:root:/root:/bin/bash
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
7)c 修改 本行替换,将匹配到的行的内容替换成新内容
~# sed ‘/root/c ROOT‘ pass
1 ROOT
ROOT:x:0:0:root
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
4adm:x:3:4:adm:/var/adm:/sbin/nologin
5lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
~# sed ‘/IPADDR/c IPADDR=172.16.254.201‘ /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=static
IPADDR=172.16.254.201
NETMASK=255.255.0.0
GATEWAY=172.16.254.1
8)y 转换的命令,对应替换
y///
y/123/ABC/
~# sed ‘y/1234/ABCF/‘ pass
Aroot:x:0:0:root:/root:/bin/bash
Bbin:x:A:A:bin:/bin:/sbin/nologin
Cdaemon:x:B:B:daemon:/sbin:/sbin/nologin
Fadm:x:C:F:adm:/var/adm:/sbin/nologin
5lp:x:F:7:lp:/var/spool/lpd:/sbin/nologin
6sync:x:5:0:sync:/sbin:/bin/sync
7shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8halt:x:7:0:halt:/sbin:/sbin/halt
9mail:x:8:AB:mail:/var/spool/mail:/sbin/nologin
A0uucp:x:A0:AF:uucp:/var/spool/uucp:/sbin/nologin
将文件中所有的小写字母转换成大写字母
~# sed ‘y/qwertyuiopasdfghjklzxcvbnm/QWERTYUIOPASDFGHJKLZXCVBNM/‘ pass
9)n next 处理匹配行的下一行,用的较少
~# sed -n ‘/root/p‘ pass
1root:x:0:0:root:/root:/bin/bash
~# sed -n ‘/root/{n;p}‘ pass //{}里面写多个命令,之间用分号分隔
2bin:x:1:1:bin:/bin:/sbin/nologin
10)q 退出 不再向模式空间读入新行
~# sed ‘/^bin/q‘ /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
~# sed ‘1q‘ pass //head -1的又一种方法
1root:x:0:0:root:/root:/bin/bash
练习:
1、将pass文件每行打印3次
~# sed ‘p;p‘ pass
2、打印passwd文件的第1行和第3行(多点编辑,用分号分隔命令)
~# sed -n ‘1p;3p‘ pass
1root:x:0:0:root:/root:/bin/bash
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
~# sed -n -e ‘1p‘ -e ‘3p‘ pass
3、使用sed修改selinux的模式为permissive
~# sed ‘7c SELINUX=permissive‘ /etc/selinux/config
4、使用sed永久修改主机名为shell
~# sed ‘$c HOSTNAME=shell‘ /etc/sysconfig/network
3、删除pass文件的第1行和最后一行
~# sed ‘1d;$d‘ pass
以下操作datafile文件
4、在匹配到Lewis的行的下一行插入“has Lewis”
~# sed ‘/Lewis/a has Lewis‘ datafile
5、在文件的第一行插入“employee‘s information”
~# sed "1i employee‘s information" datafile
11)s 查找替换
定址s/模式匹配(旧的内容)/新的内容/[修饰符]
s@@@ s### s%%%
修饰符:
g:全局替换,一行中的多个
n:n为数字,1-512 替换第n个匹配到的内容
p:打印
w:另存为,写
~# sed ‘s/root/ROOT/‘ pass | head -3 //默认只替换第一次匹配到的
1ROOT:x:0:0:root:/root:/bin/bash
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
~# sed ‘s/root/ROOT/2‘ pass | head -3 //替换每行中第2个匹配到的
1root:x:0:0:ROOT:/root:/bin/bash
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
~# sed ‘s/root/ROOT/g‘ pass | head -3 //全部替换
1ROOT:x:0:0:ROOT:/ROOT:/bin/bash
2bin:x:1:1:bin:/bin:/sbin/nologin
3daemon:x:2:2:daemon:/sbin:/sbin/nologin
练习:
1、从以root开头,到以login结尾的行,将sbin替换成bin (/etc/passwd)
~# sed ‘/^root/,/login$/s/sbin/bin/‘ /etc/passwd | head
2、将格式为2015/09/02的日期,替换为2015; 09; 02的格式(注意分号后面有空格)
~# date "+%Y/%m/%d"
2015/09/02
~# date "+%Y/%m/%d" | sed ‘s#/#; #g‘
2015; 09; 02
~# date "+%Y/%m/%d" | sed ‘s/\//; /g‘
3、将selinux配置文件中的disabled替换为enforcing,暂时不作用于原文件
~# sed ‘/SELINUX/s/disabled/enforcing/‘ /etc/selinux/config
思考题:删除文件中所有的数字 **** //一种思想,用替换去删除字符等
~# sed ‘s/[0-9]//g‘ pass
-i:直接作用于文件
~# sed ‘s/static/dhcp/‘ /etc/sysconfig/network-scripts/ifcfg-eth0
~# sed -i ‘s/static/dhcp/‘ /etc/sysconfig/network-scripts/ifcfg-eth0
~# sed -i.bak ‘s/dhcp/static/‘ /etc/sysconfig/network-scripts/ifcfg-eth0
//.bak是备份文件的后缀名
~# ls /etc/sysconfig/network-scripts/ifcfg-eth0*
ifcfg-eth0 ifcfg-eth0.bak
模式匹配时的特殊符号
^:每行的开头
给全文加注释
~# sed ‘s/^/#/‘ pass
在第8到10行的开头每行加上###
~# sed ‘s/^/###/‘ pass
$:每行的结尾
在匹配到root的行的末尾添加###
~# sed ‘/root/s/$/###/‘ pass
1root:x:0:0:root:/root:/bin/bash###
-r选项: 支持扩展正则
~# sed -r ‘s/[[:space:]]+//‘ pass
~# sed ‘s/[[:space:]]*//‘ pass
1、将history命令执行结果中编号前面的空白字符删掉
~# history | sed -r ‘s/[[:space:]]+//‘
2、删除文件中的空行和空白行
~# cat txt
adadadadada dasdasdadas
~# vim test
hello, i like you
hi, my love
like ==> liker
love ==> lover
~# sed ‘s/l..e/l..er/‘ test
hello, i liker you
hi, my lover
~# sed -r ‘s/(l..e)/\1r/‘ test
hello, i liker you
hi, my lover
like ==> Like
love ==> Love
~# sed -r ‘s/l(..e)/L\1/‘ test
hello, i Like you
hi, my Love
练习:
1、删除每行的第一个字符
2、删除每行的第二个字符
3、删除每行的倒数第一个字符
4、删除每行的倒数第二个字符
5、交换每行的第一个和第二个字符
7、awk的特殊模式
awk的完整语法
awk [选项] ‘BEGIN{动作}定址{动作}END{动作}‘ 文件列表
BEGIN{} : 在读取文件之前就执行,只执行一次;一般用于初始化分隔符、初始化变量、定义数组、打印表头等
定址{} : 这一部分可能会执行多次
END{} : 在处理完文本之后执行,只执行一次;一般用于汇总数据 比如:打印总成绩、平均成绩等等
~# awk ‘BEGIN{FS=":";print "username"}/root/{print $1}END{print "over"}‘ /etc/passwd
username
root
operator
over
说明:
BEGIN和END可以单独存在的
1)只有BEGIN,后面不需要加文件
~# awk ‘BEGIN{print "hello"}‘
hello
2)只有END,后面必须加文件,文件可以是空文件,也可以是有内容的文件
~# awk ‘END{print "end"}‘ pass
end
~# touch haha
~# awk ‘END{print "end"}‘ haha
end
3)没有BEGIN,也没有END
~# awk ‘{sum=0;sum+=$3;print $1,$3,sum}‘ employees
Tom 4424 4424
Mary 5346 5346
Sally 1654 1654
Billy 1683 1683
Tom 4424 4424
4)有BEGIN,没有END‘
~# awk ‘BEGIN{sum=0}{sum+=$3;print $1,$3,sum}‘ employees
Tom 4424 4424
Mary 5346 9770
Sally 1654 11424
Billy 1683 13107
Tom 4424 17531
5)既有BEGIN,又有END
~# awk ‘BEGIN{sum=0}{sum+=$3;print $1,$3}END{print "total:"sum}‘ employees
Tom 4424
Mary 5346
Sally 1654
Billy 1683
Tom 4424
total:17531
练习:
统计/etc目录下所有的普通文件的总大小
~# ll /etc | awk ‘BEGIN{sum=0}/^-/{sum+=$5}END{print sum}‘
1257642
8、awk的脚本
BEGIN{
命令
}
定址{
命令
}
END{
命令
}
打印ule总成绩,平均成绩
~# vim sc.awk
BEGIN{
print "This is ule score table"
}
NR>1{
ule+=$2
}
END{
print "ule‘s total score is :"ule
print "ule‘s average score is :"ule/(NR-1)
}
~# awk -f sc.awk score
This is ule score table
ule‘s total score is :246
ule‘s average score is :61.5
练习:
1、求得ULA的总成绩,平均成绩;求oracle的总成绩,平均成绩
2、样例文件staff.txt
文件内容如下:
~# cat staff.txt
id name sal date
100tom100002013/10/1
101jerry80002013/10/10
102john50002013/11/1
103mark60002013/12/10
104rose20002014/01/01
105jake15002014/01/10
1)统计每个月发出去的总工资
~# awk ‘NR>1{sal+=$3}END{print sal}‘ staff.txt
32500