文本处理三剑客之sed --超详细操作

文本处理三剑客--sed超详细使用操作

sed使用选项命令

Options:选项
  -n  只显示经过sed处理后的行
  -e  用于多个条件处理,顺序执行,即一次读取,多次处理
  -f  从文件中读取处理命令
  -i  直接更改文件,如果加后缀则先重命名原文件再创建一个新文件
  -c  需配合-i加后缀使用,处理前先复制一份原文件到备份文件,然后直接修改原文件
  -r  使用扩展正则,支持分组引用,最多支持引用9组\1到\9
  -s  如果指定了多个文件,则分别处理每个文件而非合并后再处理
  -u  不缓存数据
  -z  不换行输出
  --follow-symlinks  跟随链接跳转
​
地址:
N  匹配指定行
$  匹配最后一行
N~step    匹配指定行并以step为步进,如1~2表示奇数行,2~2表示偶数行
/regexp/  正则匹配,添加i或I表示忽略大小写匹配/xxx/i,遇到包含路径的字符/时需要转义为\/
\@regexp@  正则匹配,使用这种方式,无需转义路径,@可以替换为任意字符
/regexp/,/regexp/  正则范围匹配
N,/regexp/  指定行到正则匹配行
/regexp/,$  正则匹配行到文件末尾(即最后一行)
N,M   匹配N到M行
N,+M  匹配N到N+M行
​
命令:
a\ 追加内容到匹配行的下一行,最后的\可以省略,支持使用\n追加多行
i\ 追加内容到匹配行的上一行,同上
c\ 改写匹配行,同上
d  删除匹配行
q  退出sed脚本,可以指定退出代码
r  读取指定文件中的内容追加到当前输出
R  按行读取并追加
h  复制模式空间中的内容到内存缓冲区
H  追加模式空间中的内容到内存缓冲区
g  复制内存缓冲区的内容到模式空间
G  追加内存缓冲区的内容到模式空间
l  显示不可打印字符
n  读取匹配行的下一行复制到模式空间
N  读取匹配行的下一行追加到模式空间
p  显示匹配行
s/regexp/string/g  正则匹配并替换,可使用&来代指匹配到的内容,加g表示全部替换,加i或I表示忽略大小写,支持使用其他分隔符如@,#
w  保存匹配到的行到指定文件
y  字符替换
=  显示匹配行号
!  命令取反,如!p即显示不匹配的行
{} 匹配后如需执行多次处理需用{}括起来,如'/word/{s//& (world) /;s/^/+ /}'
​
正则表达式元字符,和grep命令的正则语法一致
^  匹配行首,如^abc匹配所有以abc开头的行
$  匹配行尾,如abc$匹配所有以abc结尾的行
^$  匹配空行
^[[:space:]]*$  匹配空白行,包括空格或tab所占的行
.  匹配除换行符(\n,\r)之外的任意单个字符,如a.c匹配abc,a2c等
*  匹配零个或多个先前字符,即匹配次数>=0次,如a*c匹配ac,aac,aaac等
.*  匹配任意长度的任意字符,如a.*c匹配ac,abc,aabbcc等
?  匹配零个或一个先前的字符,即匹配次数<=1次,如a?c匹配c,ac
+  匹配一个或多个先前的字符,即匹配次数>=1次,如a+c匹配ac,aac,aaac等
|  或匹配,如a|b|c匹配a或b或c
()  分组,如abc([1-9])?匹配abc,abc1,abc123
[]  匹配指定范围内的任意单个字符,如[Aa]bc匹配Abc,abc
[^]  取反,匹配指定范围之外的任意单个字符,如[^Aa]bc匹配除了Abc和abc之外
\  转义符,如\$匹配$本身
\<  匹配单词词首,如\<abc匹配以abc开头的单词
\>  匹配单词词尾,如abc\>匹配以abc结尾的单词
{n}  匹配n次,如a{2}匹配aa
{n,}  至少匹配n次,即>=n次,如a{2,}匹配aa,aaa等
{n,m}  匹配n-m次,包括n次和m次,即[n-m]次,其中n<=m,如a{2,4}匹配aa,aaa,aaaa
{,m}  最多匹配m次,即<=m次,如ab{,2}匹配a,ab,abb
\b  匹配单词边界,如\broot\b匹配单词root
\B  匹配非单词边界,如root\B匹配rooter而不匹配root
\w  匹配字母,数字和下划线,等同于[A-Za-z0-9_]
\W  匹配非\w的字符
\s  匹配空白字符
​

sed描述及用法

文本处理工具
​
sed [OPTION]... 'command' [file]...
sed [OPTION]... -f scriptfile [file]...

sed操作介绍

sed 是一种流编辑器,读取一行,处理一行,输出一行.sed 先读取文件中的一行内容存储到被称为模式空间 (pattern space) 的临时缓冲区中,接着根据设定的条件来处理缓冲区中的内容,多个条件则多次处理,处理完成后输出到屏幕,接着读取和处理下一行,直到文件末尾。原文件内容并没有改变,除非使用重定向存储输出.sed 主要用来自动编辑一个或多个文件;简化对多个文件执行相同的编辑处理工作;编写转换程序.
​
sed 处理的是缓冲区的数据,不影响原数据,一次读取,可以多次处理,后续的编辑命令都是应用前面命令编辑后输出的结果,所以一定要注意编辑命令的顺序问题.sed 的处理顺序,先读取文件中的一行数据保存到缓冲区,再查看地址位置是否匹配,匹配则执行编辑命令,不匹配则继续查看下一个地址位置或继续读取下一行.

sed实例操作

# sed多条件的处理流程
$ more f1
a
b
c
d
$ sed -n -e '1,3p' -e '2a111' -e '2d' f1
a
b
111
c
# 处理流程:
# 1.读取第一行,匹配第一个条件,打印输出,不匹配后两个条件,则第一行处理结束
# 2.读取第二行,匹配第一个条件,打印输出,匹配第二个条件,即在匹配行的下一行添加111,继续匹配第三个# 条件,删除第二行数据,注意这里删除的是缓冲区中的数据
# 3.读取第三行,匹配第一个条件,打印输出,不匹配后两个条件,则第三行处理结束
​
$ sed -n -e '2d' -e '1,3p' -e '2abc' f1
a
c
# 处理流程:
# 1.读取第一行,不匹配第一个条件,不处理,匹配第二个条件,打印输出,不匹配第三个条件,不处理,第一行处理结束
# 2.读取第二行,匹配第一个条件,删除处理,匹配后续两个条件,但缓冲区内容已被删除,所以输出为空,即最后不显示第二行内容
# 3.读取第三行,只匹配第二个条件,打印输出,第三行处理结束
​
$ more a
aaa
abc
aa bb cc
123
12345
a b c
bbb
ccc
# -n只显示匹配的行
$ sed -n '/aaa/p' a
aaa
# -e多个条件匹配和处理
$ sed -ne '/aaa/p' -ne '1abbb' a
aaa
bbb
# 遇到包含路径的字符/需要转义\/,或者使用其他字符代替,只需转义第一个代替的字符,如下的\@或\#
$ sed -n '/ /data /p' /etc/fstab
sed: -e expression #1, char 5: extra characters after command
$ sed -n '/ \/data /p' /etc/fstab
UUID=05c75b90-d3ef-419a-8a17-aa6340a18f29  /data  ext4  defaults 0 0
$ sed -n '\@ /data @p' /etc/fstab
UUID=05c75b90-d3ef-419a-8a17-aa6340a18f29  /data  ext4  defaults 0 0
$ sed -n '\# /data #p' /etc/fstab
# 查看文件的inode值
$ ls -il a
33602001 -rw-r--r-- 1 root root 41 Feb 28 15:04 a
# -i不加后缀则表示直接修改文件
$ sed -i '1abbb' a
# -i.bak表示先备份文件加后缀.bak,然后修改原文件
$ sed -i.bak '1abbb' a
# 通过inode可以看到-i.bak处理后是先重命名原文件为.bak,然后新建一个文件a处理
$ ls -il a*
33575026 -rw-r--r-- 1 root root 45 Feb 28 15:06 a
33602001 -rw-r--r-- 1 root root 41 Feb 28 15:04 a.bak
# 原文件a多了一行内容bbb
$ diff a a.bak
2d1
< bbb
$ rm a
$ mv a.bak a
$ ll -il a*
33602001 -rw-r--r-- 1 root root 41 Feb 28 15:04 a
# -ci.bak是复制原文件为.bak文件,然后直接编辑原文件
$ sed -ci.bak '1abbb' a
$ ll -il a*
33602001 -rw-r--r-- 1 root root 45 Feb 28 15:07 a
33601994 -rw-r--r-- 1 root root 41 Feb 28 15:07 a.bak
$ diff a a.bak
2d1
< bbb
$ more b
aaa
123
abccc
# 默认指定了多个文件,则自动合并文件内容后再处理
$ sed '1a111' a b
aaa
111
abc
...
aaa
123
abccc
# -s则分别处理每个文件,如下所有文件a和b均增加了一行111的内容
$ sed -s '1a111' a b
aaa
111
abc
...
aaa
111
123
abccc
​
# 编辑命令a追加到下一行,i追加到上一行
$ sed '1a111' a
aaa
111
abc
$ sed '1i111' a
111
aaa
abc
# q指定退出代码,显示前3行内容并退出,指定退出码为3
$ sed '3q3' a
aaa
abc
aa bb cc
$ echo $?
3
$ more aa
11
12
13
$ more bb
21
22
23
# r读取文件bb的第1行然后追加文件aa的所有内容,再读取第2行然后继续追加文件aa的内容
$ sed 'raa' bb
21
11
12
13
22
11
12
13
23
11
12
13
# 1r读取文件bb的第1行然后追加文件aa的所有内容
$ sed '1raa' bb
21
11
12
13
22
23
# R读取一行追加一行
$ sed 'Raa' bb
21
11
22
12
23
13
# c改写匹配行
$ sed '1cbbb' a
bbb
abc
aa bb cc
# d删除匹配行
$ sed '1d' a
abc
aa bb cc
$ sed '$d' a
$ sed '5,$d' a
# l显示不可打印字符
$ sed -n 'l' a
aaa$
abc$
aa bb cc$
123$
12345$
a b c$
bbb$
ccc$
# p显示匹配行
$ sed -n '1,3p' a
aaa
abc
aa bb cc
# s匹配aaa并再其后追加bbb
$ sed  's/aaa/&bbb/' a
aaabbb
abc
aa bb cc
$ sed -n '/[0-9]/p' a |sed -r 's/[0-9]+/&.&/'
123.123
12345.12345
# 也支持使用\1分组匹配引用
$ sed -n '/[0-9]/p' a |sed -r 's/([0-9]+)/&.\1/'
123.123
12345.12345
# w保存匹配行到文件b
$ sed -n '/aaa/wb' a
$ more b
aaa
# y将字符a替换为x
$ sed  'y/a/x/' a
xxx
xbc
xx bb cc
# =显示匹配的行号
$ sed -n '/aaa/=' a
1
7
# !p显示不匹配的行
$ sed -n '/aaa/!p' a
abc
aa bb cc
123
12345
a b c
bbb
ccc
# 正则匹配范围,显示从匹配aaa的行到匹配bbb的行
$ sed -n '/aaa/,/bbb/p' a
aaa
abc
aa bb cc
123
12345
a b c
aaa  aaa aaa
bbb
# 指定行到正则匹配行,显示从第5行到匹配bbb的行
$ sed -n '5,/bbb/p' a
12345
a b c
aaa  aaa aaa
bbb
# 匹配后执行多个处理条件用{}括起来
$ nl a |sed -n '/aa/{s/bb/22/;p}'
     1  aaa
     3  aa 22 cc
     7  aaa  aaa aaa
# 2~2从第2行开始匹配,并以2为步进匹配
$ seq 1 10 > aa
$ sed -n '2~2p' aa
2
4
6
8
10
# 匹配第3行到第6行
$ sed -n '3,+3p' aa
3
4
5
6
# 显示奇数行,2种方式
$ sed -n '1~2p' aa
$ sed -n 'p;n' aa
1
3
5
7
9
# 显示偶数行,2种方式
$ sed -n '2~2p' aa
$ sed -n 'n;p' aa
2
4
6
8
10
# 倒叙显示文件内容
$ sed '1!G;h;$!d' aa
10
9
8
7
6
5
4
3
2
1
# 匹配2个字符的单词,也包括数字
$ sed -n '/\b\w\{2\}\b/p' a
aa bb cc
11
# 匹配3个字符的单词,注意匹配的是行
$ sed -n '/\b\w\{3\}\b/p' a
aaa
abc
123
aaa aaa aaa
bbb
ccc
# 默认匹配大小写
$ cat file
aaaa
aaAA
AA BB
aAAa
aa bb
$ sed -n '/aa/p' file
aaaa
aaAA
aa bb
$ sed -n '/AA/p' file
aaAA
AA BB
aAAa
# 添加i或I,如/xxx/i可以忽略大小写匹配
$ sed -n '/\<aa\>/ip' file
$ sed -n '/\<aa\>/Ip' file
AA BB
aa bb
# 单词匹配可以使用\<xxx\>或\bxxx\b
$ sed -n '/\<AA\>/p' file
AA BB
$ sed -n '/\bAA\b/p' file
AA BB
$ sed -n '/\baa\b/p' file
aa bb
# 忽略大小写匹配单词
$ sed -n '/\baa\b/Ip' file
AA BB
aa bb
# 支持匹配多个单词
$ sed -n '/\baa bb\b/p' file
aa bb
# 显示空行行号,但是不包括空格行和tab空行,!=显示非空行号
$ sed -n '/^$/=' f1
# 显示非空行内容
$ sed -n '/^$/!p' f1
# 注释非空行
$ sed 's/[^$]/# &/' f1
# 删除空行
$ sed '/^$/d' f1
# 显示空行行号,包括空格行和tab行
$ sed -n '/^[[:space:]]*$/=' f1
# 删除空白行和#开头的行
$ sed '/^#/d;/^[[:space:]]*$/d' f1
# 删除每一行开头的空白(空格和tab),即左对齐排列全文
$ sed 's/^[ \t]*//' f1
# 删除每一行最后的空白(空格和tab)
$ sed 's/[ \t]*$//' f1
# 删除行尾的逗号,
$ sed 's/,$//' file > file.nocomma
# 删除行尾的最后一个字符,此为通用命令
$ sed 's/.$//' file > file.nolast
# 在a后面增加b,同时在被修改的行前面增加+号
$ sed '/a/{s//&b/;s/^/+ /}' f1
# 匹配word,在其后添加 (world) ,同时在行首添加+ 号
$ sed '/word/{s//& (world) /;s/^/+ /}' f1
# -e可以省略,可简写为第2条命令
$ sed -e '1,3p' -e '2d' f1
$ sed '1,3p;2d' f1
# 统计行数,相当于wc -l
$ sed -n '$=' f1
# 显示文件内容,相当于cat
$ sed '' f1
# 清空文件内容
$ sed -ni '' f1
# 清空前先复制文件到xxx.bak备份文件
$ sed -cni.bak '' f1
# 查找匹配的行
sed -n '/192.*centos/p' f1
# 注释匹配的行
sed -i '/192.*centos/s/^/#/' f1
# 取消注释匹配的行
sed -i '/192.*centos/s/#//' f1
# 全局替换
$ echo aaaaaa | sed 's/a/A/g'
AAAAAA
# 只替换第二个匹配项
$ echo aaaaaa | sed 's/a/A/2'
aAaaaa
# 从第二个匹配项开始替换到最后
$ echo aaaaaa | sed 's/a/A/2g'
aAAAAA
# 正则表达式\w\+表示匹配每一个单词,&表示引用匹配到单词
$ echo "this is a test line" | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]
# 将数字用逗号分隔
$ echo 12345678 |sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
12,345,678
# 日期格式转换
echo "2018/12/31" | sed 's#/#-#g'
# 注意b*匹配零个或多个b,有三个字符abc被替换成了1a,1,c1
$ echo abc | sed 's/b*/1/g'
1a1c1
# 取文件名,但是推荐使用basename命令
$ echo "/etc/sysconfig/network-scripts/ifcfg-eth0" |sed -r 's@(^/.*/)([^/]+/?)@\2@'
$ basename /etc/sysconfig/network-scripts/ifcfg-eth0
# 取目录名,但是推荐使用dirname命令
$ echo "/etc/sysconfig/network-scripts/ifcfg-eth0" |sed -r 's@(^/.*/)([^/]+/?)@\1@'
$ dirname /etc/sysconfig/network-scripts/ifcfg-eth0
​
# 分组引用和忽略大小写匹配替换
$ cat file
http://www.a.com/a/b/c/d-ef/wef/aaa.jpeg
https://www.aaa.com/a/xxb/eec/d-ef/wf/bbb.jpg
http://www.b.com/a/b/c/d-ef/wef/cca.png
https://img.aa.com/a/xxb/eec/bb.jpeg
http://image.aaa.com/a/xxb/eec/d-ef/dd.jpg
aa,http://img.aa.com/a/xxb/eec/bb.JPEG
# 匹配http或https替换为https,匹配.jpeg结尾替换为.jpg,url中间内容保持不变,匹配忽略大小写,且为全局匹配
$ sed -rn 's@(https?)(.*)(.jpeg$)@https\2.jpg@igp' file
https://www.a.com/a/b/c/d-ef/wef/aaa.jpg
https://img.aa.com/a/xxb/eec/bb.jpg
aa,https://img.aa.com/a/xxb/eec/bb.jpg
# 替换后的结果如下
$ sed -r 's@(https?)(.*)(.jpeg$)@https\2.jpg@ig' file
https://www.a.com/a/b/c/d-ef/wef/aaa.jpg
https://www.aaa.com/a/xxb/eec/d-ef/wf/bbb.jpg
http://www.b.com/a/b/c/d-ef/wef/cca.png
https://img.aa.com/a/xxb/eec/bb.jpg
http://image.aaa.com/a/xxb/eec/d-ef/dd.jpg
aa,https://img.aa.com/a/xxb/eec/bb.jpg
​
# 转换DOS的换行符(CR/LF)为Unix格式
$ file a.txt
a.txt: ASCII text, with CRLF line terminators
# windows文件中显示^M
$ cat -A a.txt
a^M$
b^M$
c^M$
# 以下两个命令均可以转换
$ sed 's/.$//' a.txt
$ sed 's/\x0D$//' a.txt
# 转换Unix的换行符(LF)为DOS格式
# unix文件中只显示$
$ cat -A a
aaa$
abc$
aa bb cc$
# 使用以下命令转换
$ sed 's/$/\r/' a
​
# 匹配以Host 开头的行到文件末尾(最后一行)之间的内容,删除包括Ciphers 的行,注意处理命令需要使用{}括起来,用于区分过滤命令和处理命令
sed -i '/^Host /,${/.*Ciphers /d}' /etc/ssh/ssh_config
​
# 先删除注释行和配置行,然后新增配置行到文件末尾,注意关键字的匹配,建议先通过grep命令筛查,避免误删除
# 推荐在脚本中使用如下两条命令的格式来修改配置文件,可以重复执行,实现幂等
sed -i '/.*Port /d' /etc/ssh/sshd_config
echo 'Port 22' >> /etc/ssh/sshd_config
​
# 引号原则: 显示引号需要加\转义,转义后的引号不能影响成组的引号,如果影响需要使用一组单引号括起来
# 显示双引号"
# 引号说明: 最外侧的两个单引号表示awk语句,里面的一组双引号表示print语句,中间的一个双引号为想要显示的内容,但是双引号需要加\转义
echo |awk '{print "\""}'
# 显示单引号'
# 引号说明: 最外侧的两个单引号表示awk语句,里面的一组双引号表示print语句,中间的一个单引号为想要显示的内容,但是单引号需要加\转义,转义后的单引号和awk语句的单引号冲突,所以需要在使用一组单引号括起来
echo |awk '{print "'\''"}'
​
# 显示双引号加字符"aa"
echo |awk '{print "\"aa\""}'
# 显示单引号加字符'aa'
echo |awk '{print "'\''aa'\''"}'
# 显示双引号和单引号"aa","bb's"
echo |awk '{print "\"aa\",\"bb'\''s\""}'
​
echo 'net.ipv4.ip_forward=0' |awk -F= '{printf"- sysctl:\n    name: %s\n    value: '\''%s'\''\n",$1,$2}' >> sysctl.yml
​
​
# 查看匹配行的下一行"/xxx/{n;p}""
$ sed -rn "/1. [ \'a-z-]+/{n;p}" a.txt
(说明)
# 尝试替换并显示"/xxx/{n;s/x/y/;p}"
$ sed -rn "/1. [ \'a-z-]+/{n;s/说明/说明123/;p}" a.txt
(说明123)
# 更改文件
$ sed -ri "/1. [ \'a-z-]+/{n;s/说明/说明123/}" a.txt
# 尝试替换并显示
$ sed -r "/^1. like$/{n;s/.*/(说明123)/}" a.txt
# 更改文件
$ sed -ri "/^1. like$/{n;s/.*/(说明123)/}" a.txt
​
​
# 匹配包含空格的单词或短语,括号可以省略
$ grep -E '^1. ([a-z-]+ )' a.txt
$ grep -E '^1. ([ a-z-]+ )' a.txt
$ grep -E '^1. ([a-z-]+ ){1,}' a.txt
$ sed  -rn '/^1. ([a-z-]+ )/p' a.txt
# 全局替换g
$ sed  -rn '/^1. ([a-z-]+ )/{s/ /-/g;p}' a.txt
# 仅替换第二个匹配项
$ sed  -rn '/^1. ([a-z-]+ )/{s/ /-/2;p}' a.txt
# 从第二个匹配项开始替换
$ sed  -rn '/^1. ([a-z-]+ )/{s/ /-/2g;p}' a.txt
​
# 在文件开头添加一行空行
sed '1s/^/\n/' file
# 在文件末尾添加一行空行
sed '$s/$/\n/' file
# 追加内容xxx到文件开头行,\n表示换行
sed '1s/^/xxx\n/' file
# 或
sed '1ixxx' file
# 追加内容xxx到文件末尾
sed '$axxx' file
​
# 在每一行的后面添加空行,包括空行后面也会添加新的空行
sed G file
# 在每一行的后面添加两行空行,包括空行后面也会添加两行空行
sed 'G;G' file
# 在第一行的后面添加空行,即在第二行添加空行
sed 1G file
# 在每一行的前面添加空行,包括空行后面也会添加新的空行
sed '{x;p;x}' file
# 在每一行的前面添加两行空行
sed '{x;p;x;x;p;x}' file
# 在第一行的前面添加空行,即在第一行添加空行
sed '1{x;p;x;}' file
# 先删除空行,然后在每一行后面添加空行
sed '/^$/d;G' file
​
​
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值