文章目录
sed命令
sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
参数说明
参数 | 说明 |
---|---|
-i | 直接修改读取的文件内容,而不是输出到终端 |
-e | 以选项中指定的script来处理输入的文本文件 |
-f | 以选项中指定的script文件来处理输入的文本文件 |
-h | 或–help显示帮助 |
-n | 仅显示script处理后的结果 |
-V | 或–version 显示版本信息 |
动作说明
动作 | 说明 |
---|---|
a | 新增,a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行) |
p | 打印,通常 p 会与参数 sed -n 一起运行 |
c | 取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行 |
d | 删除,删除选择的行; |
D | 删除模板块的第一行 |
i | 插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); |
s | 取代,通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦! |
h | 拷贝模板块的内容到内存中的缓冲区; |
H | 追加模板块的内容到内存中的缓冲区; |
g | 获得内存缓冲区的内容,并替代当前模板块中的文本; |
G | 获得内存缓冲区的内容,并追加到当前模板块文本的后面; |
l | 列表不能打印字符的清单; |
n | 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令; |
N | 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码; |
p | 打印模板块的行。 P(大写) 打印模板块的第一行; |
q | 退出Sed; |
r | file 从file中读行; |
b | lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾; |
t | label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾; |
T | label 错误分支,从最后一行开始,一旦发生错误或T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾; |
w | file 写并追加模板块到file末尾; |
W | file 写并追加模板块的第一行到file末尾; |
! | 表示后面的命令对所有没有被选定的行发生作用; |
= | 打印当前行号; |
# | 把注释扩展到下一个换行符以前; |
sed替换标记
标记 | 说明 |
---|---|
g | 表示行内全面替换; |
p | 表示打印行; |
w | 表示把行写入一个文件; |
x | 表示互换模板块中的文本和缓冲区中的文本; |
y | 表示把一个字符翻译为另外的字符(但是不用于正则表达式); |
\1 | 子串匹配标记; |
& | 已匹配字符串标记; |
sed元字符集
字符 | 说明 |
---|---|
^ | 匹配行开始,如:/^sed/匹配所有以sed开头的行; |
$ | 匹配行结束,如:/sed$/匹配所有以sed结尾的行; |
. | 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d; |
* | 匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行; |
[] | 匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed; |
[^] | 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行; |
…… | 匹配子串,保存匹配的字符,如s/(love)able/\1rs,loveable被替换成lovers; |
& | 保存搜索字符用来替换其他字符,如s/love/&/,love这成love; |
< | 匹配单词的开始,如:/\ |
> | 匹配单词的结束,如/love>/匹配包含以love结尾的单词的行; |
x{m} | 重复字符x,m次,如:/0{5}/匹配包含5个0的行; |
练习:
①#全局替换:g
sed 's/book/books/g' file #/g 标记会替换每一行中的所有匹配
echo sksksksksksk | sed 's/sk/SK/2g' #需要从第N处匹配开始替换时,可以使用 /Ng
[root@zt ~]# echo sksksksksksk | sed 's/sk/SK/2g'
skSKSKSKSKSK
②#定界符
命令中字符 / 在sed中作为定界符使用,也可以使用任意的定界符
sed 's:test:TEXT:g' ---> : : :
sed 's|test|TEXT|g' ---> | | |
#定界符出现在样式内部时,需要进行转义:
#组合多个表达式
sed 's/\/bin/\/usr\/local\/bin/g'
sed '表达式' | sed '表达式'
sed '表达式; 表达式'
③#删除:d
sed '/^$/d' file #删除空白行
sed '2d' file #删除第二行
sed '2,$d' file #删除第二行到最后一行
sed '$d' file #删除最后一行
sed '/^test/'d file #删除以test开头的行
④#已匹配字符串标记&
#正则表达式 \w\+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词
[root@zt ~]# echo "this is a test line" | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]
#所有以192.168.0.1开头的行都会被替换成它自已加localhost:
[root@zt ~]# sed 's/^192.168.0.1/&localhost/' file
hello
this is a test line
192.168.0.1localhost
⑤#子串匹配标记\1
#love被标记为1,所有loveable会被替换成lovers,并打印出来
sed -n 's/\(love\)able/\1rs/p' file
[root@zt ~]# echo this is digit 7 in a number | sed 's/digit\([0-9]\)/\1/'
this is digit 7 in a number
[root@zt ~]# echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'
this is 7 in a number
#命令中 digit 7,被替换成了 7。样式匹配到的子串是 7,\(..\) 用于匹配子串,
对于匹配到的第一个子串就标记为 \1,依此类推匹配到的第二个结果就是 \2
[root@zt ~]# echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
BBB aaa
[root@zt ~]# echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\1/'
aaa
[root@zt ~]# echo abcd | sed 's/\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)/\2/'
b
[root@zt ~]# echo abcd | sed 's/\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)/\1\2/'
ab
⑥#多点编辑,e
#-e选项允许在同一行里执行多条命令
sed -e '1,5d' -e 's/test/check/' file
#上面sed表达式的第一条命令删除1至5行,第二条命令用check替换test。
命令的执行顺序对结果有影响。如果两个命令都是替换命令,
那么第一个替换命令将影响第二个替换命令的结果
⑦#选定行的范围:,(逗号)
#所有在模板test和check所确定的范围内的行都被打印
sed -n '/test/,/check/p' file
#打印从第5行开始到第一个包含以mail开始的行之间的所有行:
[root@zt ~]# sed -n '5,/^mail/p' /etc/passwd
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#对于模板test和west之间的行,每行的末尾用字符串aaa bbb替换
sed '/test/,/west/s/$/aaa bbb/' file
⑧#转换:y
#把1~10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令
sed '1,10y/abcde/ABCDE/' file
⑨#从文件读入:r
#file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,
则file的内容将显示在所有匹配行的下面
sed '/test/r file' filename
⑩#写入文件:w
#在example中所有包含test的行都被写入file里
sed -n '/test/w file' example
⑾#追加(行下):a
#将 this is a test line 追加到 以test 开头的行后面
sed '/^test/a\this is a test line' file
sed -i '2a\this is a test line' test.conf #第2行之后插入
⑿#插入(行上)
#i\命令 将 this is a test line 追加到以test开头的行前面
sed '/^test/i\this is a test line' file
sed -i '5i\this is a test line' test.conf
⒀#下一个:n
#如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,
然后继续
sed '/test/{ n; s/aa/bb/; }' file
测试:
1.以行为单位的删除
①将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行打印出来!
[root@bogon /home/Sudley]#nl /etc/passwd |sed -n '2,5p'
②删除第 2 行
[root@bogon /home/Sudley]#nl /etc/passwd |sed '2d'
③要删除第 3 到最后一行
[root@bogon /home/Sudley]#nl /etc/passwd |sed '3,$d'
2.以行为单位的新增
①在第三行后加上newline字样
[root@bogon /home/Sudley]#sed -e 3a\newline testfile
②在第三行前加上newline字样
[root@bogon /home/Sudley]#sed -e 3i\newline testfile
③在第二行后面加入两行字,例如newline1 和 newline2
cat testfile|sed -e '2a newline\nnewline2'
3.以行为单位的替换与显示
①将/etc/passwd中第2-5行的内容取代成为newline
[root@bogon /home/Sudley]#nl /etc/passwd |sed '2,5c newline'
②搜索 /etc/passwd有root关键字的行
[root@bogon /home/Sudley]#nl /etc/passwd |sed -n '/root/p'
4.数据的搜寻并删除
①删除/etc/passwd所有包含root的行,其他行输出
[root@bogon /home/Sudley]#nl /etc/passwd |sed '/root/d'
5.数据的搜寻并执行命令
①搜索/etc/passwd,找到root对应的行,把bash替换为blueshell,再输出这行
[root@bogon /home/Sudley]#nl /etc/passwd |sed -n '/root/{s/bash/blueshell/;p;q}'
1 root:x:0:0:root:/root:/bin/blueshell
[root@bogon /home/Sudley]#p 打印 q 输出 {;;}花括号中间用分号隔开
6.数据的搜寻并替换命令
除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并代。
sed 's/要被取代的字串/新的字串/g’
7.多个命令同时编辑
①一条sed命令,删除/etc/passwd第3行到第五行的数据,并把sbin替换为bin
[root@bogon /home/Sudley]#nl /etc/passwd |sed -e '3,30d' -e 's/sbin/bin/'
8.直接修改文件内容(危险动作)
sed 可以直接修改文件的内容,不必使用管道命令或数据流重导向! 不过由于这个动作会直接修改到原始的文件,所以千万不要随便拿系统配置来测试!
9.练习:Week41.config
打印所有生日在十一月或十二月的行
[root@bogon /home/Sudley]#sed -n '/1[12]\//p' week41.config
在以Kare开头的行末尾加上3颗星
[root@bogon /home/Sudley]#sed -n 's/^Kare.*$/&***/p' week41.config
将所有包含Jose的行都替换为JOSE HAS RETIRED
[root@bogon /home/Sudley]#sed -n '/Jose/c XXXXX' week41.config
删除所有空行
[root@bogon /home/Sudley]#sed '/^$/d' week41.config
10.sed扩展延伸版:难度++
/etc/passwd中的练习,为更简洁的表示 只取后三行
[root@bogon /home/Sudley]#cat /etc/passwd |tail -n 3 > testfile
[root@bogon /home/Sudley]#cat testfile
setroubleshoot:x:983:975::/var/lib/setroubleshoot:/sbin/nologin
xguest:x:1002:1002:Guest:/var/lib/xguest/home/xguest:/bin/bash
ipsilon:x:982:974:Ipsilon Server:/var/lib/ipsilon:/sbin/nologin
1.删除文件每行的第一个字符
[root@bogon /home/Sudley]#sed 's/\(.\)\(.*\)/\2/' testfile
2.删除文件每行的第二个字符
[root@bogon /home/Sudley]#sed 's/\(.\)\(.\)\(.*\)/\1\3/' testfile
3.删除文件每行的第二个单词
[root@bogon /home/Sudley]#sed 's/\([a-Z]\+\)\([^a-Z]\+\)\([a-Z]\+\)\(.*\)/\1\2\4/' testfile
4.删除文件每行的倒数第二个单词
[root@bogon /home/Sudley]#sed -r 's/(.*)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]*$)/\1\2\4\5/' testfile
5.交换每行的第一个字符和第二个字符
[root@bogon /home/Sudley]#sed -r 's/(.)(.)(.*)/\2\1\3/' testfile
6.交换每行的第一个字符和第二个单词
[root@bogon /home/Sudley]#sed 's/\(^[a-Z0-9]\)\([a-Z0-9]*[^a-Z0-9]\{1,\}\)\([a-Z0-9]\{1,\}\)/\3\2\1/g' testfile
7.交换每行的第一个单词和最后一个单词
[root@bogon /home/Sudley]#sed -r 's/([a-Z]+)([^a-Z]+)(.*)([^a-Z]+)([a-Z]+)([^a-Z]*$)/\5\2\3\4\1\6/' testfile
8.删除一个文件中所有的数字
[root@bogon /home/Sudley]#sed 's/[0-9]//g' testfile
setroubleshoot:x::::/var/lib/setroubleshoot:/sbin/nologin
xguest:x:::Guest:/var/lib/xguest/home/xguest:/bin/bash
ipsilon:x:::Ipsilon Server:/var/lib/ipsilon:/sbin/nologin
9.删除每行开头的所有空格
[root@bogon /home/Sudley]#sed -r 's/^ +//g' /etc/grub2.cfg
10.用制表符替换文件中出现的所有空格
[root@bogon /home/Sudley]#sed -r 's/ +/\t/g' testfile
setroubleshoot:x:983:975::/var/lib/setroubleshoot:/sbin/nologin
xguest:x:1002:1002:Guest:/var/lib/xguest/home/xguest:/bin/bash
ipsilon:x:982:974:Ipsilon Server:/var/lib/ipsilon:/sbin/nologin
11.把所有大写字母用括号()括起来
[root@bogon /home/Sudley]#sed -r 's/([A-Z])/(\1)/g' testfile
setroubleshoot:x:983:975::/var/lib/setroubleshoot:/sbin/nologin
xguest:x:1002:1002:(G)uest:/var/lib/xguest/home/xguest:/bin/bash
ipsilon:x:982:974:(I)psilon (S)erver:/var/lib/ipsilon:/sbin/nologin
12.打印每行3次
[root@bogon /home/Sudley]#sed 'p;p' testfile
setroubleshoot:x:983:975::/var/lib/setroubleshoot:/sbin/nologin
setroubleshoot:x:983:975::/var/lib/setroubleshoot:/sbin/nologin
setroubleshoot:x:983:975::/var/lib/setroubleshoot:/sbin/nologin
xguest:x:1002:1002:Guest:/var/lib/xguest/home/xguest:/bin/bash
xguest:x:1002:1002:Guest:/var/lib/xguest/home/xguest:/bin/bash
xguest:x:1002:1002:Guest:/var/lib/xguest/home/xguest:/bin/bash
ipsilon:x:982:974:Ipsilon Server:/var/lib/ipsilon:/sbin/nologin
ipsilon:x:982:974:Ipsilon Server:/var/lib/ipsilon:/sbin/nologin
ipsilon:x:982:974:Ipsilon Server:/var/lib/ipsilon:/sbin/nologin
13.隔行删除
[root@bogon /home/Sudley]#sed '0~2 {=;d}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
2
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@bogon /home/Sudley]#sed '0~3 {=;d}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
3
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
9
14.把文件从第1行到第2行复制到第4行后面
[root@bogon /home/Sudley]#sed '1h;2,2H;4G' testfile
15.只显示每行的第一个单词
[root@bogon /home/Sudley]#sed 's/\([a-Z]\+\)\([^a-Z]\+\)\(.*\)/\1/' testfile
ipsilon
setroubleshoot
xguest
16.将格式为 mm/yy/dd 的日期格式换成 mm-yy-dd
[root@bogon /home/Sudley]#date '+%m/%y/%d' |sed 's#/#-#g'
08-19-06
17.去掉ssh配置文件中的带#行和空行
[root@bogon /home/Sudley]#sed 's/#.*$//g' /etc/ssh/sshd_config | sed '/^$/d'
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
UsePrivilegeSeparation sandbox
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/libexec/openssh/sftp-server
[root@bogon /home/Sudley]#