在做数据开发中,经常需要通过shell脚本/命令来针对文本进行预处理,sed是一个很强大的流式处理命令,笔者几乎每天都会用到,在这统一梳理总结了下! 其实 sed 很简单,比vim简单很多了!
模式匹配到的行
被读入该空间中不能直接作用于该空间
,在进行数据处理时作为“暂存区域”联想记忆: 模式对应G(在左边), 交换对应H(在右边)
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
man sed
模式空间
的所有内容(除非指定了-n
参数)-v
参数(建议)-e
: 支持多个编辑命令sed -e '1,5d' -e 's/test/check/' example
- 一个比-e更好的命令是`--expression`。它能给sed表达式赋值。
`sed --expression='s/test/check/' --expression='/love/d' example`
^
#锚定行的开始 如:/^sed/匹配所有以sed开头的行。
$
#锚定行的结束 如:/sed$/匹配所有以sed结尾的行。
.
#匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。
*
#匹配零或多个字符 如:/*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开头的单词的行。
\>
#锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。
x\{m\}
#重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。
x\{m,\}
#重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。
x\{m,n\}
#重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。
#在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。
$ sed 's/test/mytest/g' example
#s选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。
$ sed -n 's/^test/mytest/p' example
#&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。
$ sed 's/^192.168.0.1/&localhost/' example
#love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。
$ sed -n 's/\(love\)able/\1rs/p' example
#不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。
$ sed 's#10#100#g' examplex
#选定行的范围:逗号
#所有在模板test和check所确定的范围内的行都被打印。
$ sed -n '/test/,/check/p' example
#打印从第五行开始到第一个包含以test开始的行之间的所有行。
$ sed -n '5,/^test/p' example
#对于模板test和west之间的行,每行的末尾用字符串sed test替换。
$ sed '/test/,/check/s/$/sed test/' example
#如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。
$ sed '/test/{ n; s/aa/bb/; }' example
# 替换匹配到的文本
sed -i "s|^\(.*\)#\(SSLCertificateChainFile\).*|\1\2 /etc/apache2/ssl/1_root_bundle.crt|g" default-ssl.conf
# 替换匹配到的文本
sed -i "s+download.docker.com+${DOCKER_RE_REPO}+" /etc/yum.repos.d/docker-ce.repo
# 匹配再替换
sed -i "/^baseurl=http:/ { s,http://.*/hdp,http://${YUM_SERVER_IP}/hdp, } " hdp-utils.repo
# 匹配
# 如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。
sed '/test/{ n; s/aa/bb/; }' example
# \和;都得转义
# 匹配slash无法用其他字符替换
# a:在匹配行的下一行追加, \可以不加,但加上\表示后面为追加内容,且表示空格也能插入
sed -i "/\sinclude \/etc\/nginx\/conf.d\/\*.conf\;/a\ include /deploy/nginx/*.conf;" /etc/nginx/nginx.conf.bak
a\
: 在当前行后面加入一行文本i\
: 在当前行上面插入文本c
: 用新的文本改变本行的文本q
: 退出Sedr
: 从file中读行w
: 表示把行写入一个文件 (W: 追加)=
: 打印当前行号码#
: 把注释扩展到下一个换行符以前。y
: 一个字符翻译为另外的字符(但是不用于正则表达式)
# 从文件读入:r命令
# file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。 sed '/test/r file' example
# 写入文件:w命令
#在example中所有包含test的行都被写入file里。
sed -n '/test/w file' example
# 追加命令:a命令
# this is a example'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。
sed '/^test/a\\--->this is a example' example
# 插入:i命令
# 如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。
sed '/test/i\\
new line
-------------------------' example
#变形:y命令
#把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。
sed '1,10y/abcde/ABCDE/' example
#退出:q命令
#打印完第10行后,退出sed
sed '10q' example 。
模式空间
n
: 下一行 ,模式空间内容被覆盖N
: 将当前行和下一行(中间\n保留),一起追加到模式空间
[root@VM_0_6_centos ~]# seq 6 | sed -n '1{n;p}'
2
seq 6 | sed -n '1{N;p}'
1
2
[root@VM_0_6_centos ~]# seq 6 | sed -n '2{N;p}'
2
3
[root@VM_0_6_centos ~]# seq 6 | sed -n '2{n;p}'
3
交换空间
h
: 用模式空间内容覆盖交换空间H
: 将模式空间内容追加到交换空间p/P
: 模式空间输出x
: 交换空间&模式空间内容交换g
: 将交换空间的内容,覆盖到模式空间G
: 将交换空间的内容,追加到模式空间
sed -e '/test/h' -e '/check/x' example
[root@VM_0_6_centos ~]# seq 6 | sed '1h;3g'
1
2
1
4
5
6
[root@VM_0_6_centos ~]# seq 6 | sed '1h;3G'
1
2
3
1
4
5
6
sed -n '/CST/h;/syncing/{x;//!p;g;P}
//!
:简写,拿到最近的匹配结果,!
表示若匹配不到模式空间,删除 模式空间没有回车符,D/d一样 D/d执行后,都会跳到下一行(不管模式空间是否有内容)
#删除第N行
sed -i 'Nd' filename
#删除第N~M行
sed -i 'N,Md' filename # file的[N,M]行都被删除
#删除shell变量表示的行号(配合for等语句使用)
sed -i "${var1},${var2}d" filename # 这里引号必须为双引号
#删除最后一行
sed -i '$d' filename
sed '/./{H;d;x;/hello/!d
awk -v RS=' ' "/hello/
cat >test.txt <<EOF
1111
2222
3333hello
4444
5555
6666
EOF
awk -v RS=' ' "/hello/" test.txt
3333hello
4444
$d
)seq 7 | sed ':a;$d;N;2,5ba;P;D'
a~b
:a起始点,b间隔seq 10 | sed -n '1~3p'
1~3
: 1-从什么时候开始 ,3表示间隔3行seq 10 | sed -n '0~3p'
seq 10 | awk 'NR%3==1'
1
4
7
10
依次匹配
addr1, addr2
,匹配到即进行操作 addr1:匹配到后执行(开关打开),如果当前行>addr1
addr2:匹配到后执行(开关关闭)
seq 5 | sed '1,2d;1,2d'
因为3>1
,所以匹配成功,执行d删除第3行发现2<4
,匹配不成功,关闭,所以第4行不做d操作命令全部关闭
,直接输出cat >test.txt <<EOF
a1
a2
a3
EOF
# 输出1-3行
sed '1,3{s/a/ax/}' test.txt
ax1
ax2
ax3
# 第一行就匹配到了a
sed '0,/a/{s/a/ax/}' test.txt
ax1
a2
a3
# 第一行匹配到1, 第二行匹配到a
sed '1,/a/{s/a/ax/}' test.txt
ax1
ax2
a3
# 一直匹配不到x
sed '1,/x/{s/a/ax/}' test.txt
ax1
ax2
ax3
多用于做循环 t: 没有匹配到时跳转到label,无label则跳转到结尾
b: 调准到特定的label
:a
: 定义label acat >test.txt <<EOF
1
2
1
3
1
1
EOF
sed '/1/{:a;n;s/1/0/;tb;ba;:b}' test.txt
1
2
0
3
1
0
echo abc | sed 's/.*/&\n&/'
&
即引用前面匹配的结果seq 5 | sed -n 'x;p'
seq 5 | sed -n 'x;p;x'
sed '$!N;$!D'
, sed 'N;D'
, sed '$!D;D'
find . -type f -print0 | xargs -0 sed -i "s/<SERVER_NAME>/${SVR_NAME}/g"
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。