三剑客之sed

Posted xiaofeiweb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三剑客之sed相关的知识,希望对你有一定的参考价值。

sed

Stream EDitor
流编辑器,逐行过滤和替换文本
 
工作特点
默认不编辑源文件,仅对模式空间中的数据做处理,处理结束后,将模式空间输出至屏幕
 

工作原理

sed命令将当前处理的行读入自己的模式空间(pattem space)进行处理,处理完把结果打印至屏幕,并清空模式空间,然后再将下一行读入模式空间进行处理输出,以此类推,直到最后一行.
还有一个空间叫保持空间,又称暂存空间,可以暂时存放一些处理的数据,但不能直接输出,只能放到模式空间输出.
这两个空间其实就是在内存中初始化的一个内存区域,存放正在处理的数据和临时存放的数据.
 

使用格式

sed [OPTIONS]... ‘script‘ inputfile...
sed OPTIONS ‘/PATTERN/COMMAND‘ FILE_NAME
 

地址定界符

单地址
  n: 指定的行(n为数字)
  /pattern/: 被此处模式所能够匹配到每一行
地址范围
  m,n: 从m到n行
  m,+n: 从第m行到往后n行
  /pat1/,/pat2/: 表示从第一次匹配pattern1模式的行开始,到第一次匹配pattern2模式的行结束,取中间所有的行
  m,/pat1/: 从第m行到第一次匹配到pat1
$: 表示最后一行
# 删除第二行
sed 2d file

# 删除第二行到最后一行
sed 2,$d file

# 删除最后一行
sed $d file

# 删除文件中以test开头的行
sed /^test/d file
 

常用选项(option)

-n: 静默模式,不打印模式空间内的内容
-e script: 多点编辑,允许在同一行里执行多条命令,使用分号;隔开
sed -e 1,5d -e s/test/check/ file

# 注: 上面sed表达式的第一条命令删除1至5行,第二条命令用check替换test。命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果

# 和 -e 等价的命令是 --expression:
sed --expression=s/test/check/ --expression=/love/d file
 
-f file: 从指定文件file中读取编辑脚本
sed [options] -f scriptfile file(s)

# sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行
-r: 支持使用扩展正则表达式
-i: 直接修改原文件(此操作有风险)
 

处理命令(command)

多个处理命令,使用分号;隔开
p: 打印模式空间中的内容,仅打印符合条件的内容,一般配合-n来使用
# 显示/etc/fstab中以/开头的行,/为特殊符号,需转义
sed -n /^\//p /etc/fstab
 
d: 删除符合条件的行(模式空间中的行)
# 删除文件/etc/fstab中第一行,把剩下的内容显示到屏幕上,原文件内容不会发生任何改变
sed 1d /etc/fstab

# 删除带有oot的行,如果匹配字符串,需要用/隔开
sed ‘/oot/d /etc/fstab
 
a \‘text‘: 在行后面追加文本,支持使用\n换行符实现多行追加
i \‘text‘: 在行前面插入文本,支持使用\n换行符实现多行插入
c \‘text‘: 替换符合条件的行为单行或多行文本
w /path/to/somefile: 保存模式空间中的内容至指定文件中
r /path/from/somefile: 读取指定文件的文本流至模式空间中的行后
# 将文件/etc/fstab中包含有oot的行另存至文件/tmp/oot.txt文件中
sed /oot/w /tmp/oot.txt /etc/fstab

# 把/etc/issue文件的内容添加到/etc/fstab文件内容第二行的后面
sed 2r /etc/issue /etc/fstab 
 
=: 显示符合条件的行的行号,为模式空间中的行打印行号
D: 删除多行模式空间中的所有行
h: 把模式空间中的内容覆盖至保持空间中
H: 把模式空间中的内容追加至保持空间中
g: 从保持空间取出数据并覆盖至模式空间中
G: 从保持空间取出内容并追加至模式空间中
x: 把模式空间中的内容与保持空间中的内容进行互换
n: 读取匹配到的行的下一行至模式空间
N: 追加匹配到的行的下一行至模式空间
技术分享图片
cat test.txt
"""
1
2
3
4
5
6
"""

# 逆序显示文本内容
sed 1!G;h;$!d test.txt
"""
说明:
读第一行,将第一行读取到自己的模式空间中:
1!G是指除了第一行,其他行都从保持空间取出并追加至模式空间中,那么第一行不会追加;
h是把模式空间中的第一行数据覆盖至保持空间中,此时保持空间中有了第一行数据,此时,模式空间和保持空间都有了第一行数据;
$!d是指除了最后一行都删除,那么模式空间中的数据不是最后一行,则执行后面删除操作

读第二行至模式空间中:
先从保持空间中取出第一行的数据,追加到模式空间中,此时模式空间中有了第二行数据和第一行数据,然后执行h,模式空间中的内容覆盖至保持空间中,此时保持空间中的数据从上到下,有了第二行数据,第一行数据,最后判断是否为最后一行,否则删除;

以此类推,当读取到最后一行数据至模式空间中:
此时的模式空间中存在的是最后一行数据,而保持空间中按从上到下顺序应该是:倒数第二行数据,倒数第三行数据,...,然后执行G,从保持空间取出内容并追加至模式空间中,此时的模式空间中的数据则形成了倒序的方式,然后执行h,把模式空间中的内容覆盖至保持空间中,此时模式和保持空间的数据都是以倒序的方式存放的数据,最后判断是否为最后一行,很明显是最后一行,那么就不会再执行删除操作

最后打印出模式空间中的内容
"""

# 取出最后1行
sed $!d /etc/passwd

# 取出最后2行
sed $!N;$!D /etc/passwd

# 每一行后面追加一个空白行
sed G /etc/passwd

# 全部替换成空白行
sed g /etc/passwd

# 显示偶数行
sed -n n;p test.txt

# 显示奇数行
sed n;d /etc/passwd

# 删除原有的所有空白行,而后为所有的非空白行后添加一个空白行
sed /^$/d;G /etc/passwd

# 删除原有的所有空白行,而后为所有的非空白行后添加一个空白行
sed /^$/d;G /etc/passwd

# 显示最后一行的行号,一般可用于显示文本的总行
sed -n $= /etc/fstab

# 显示所有行的行号,但空行不显示行号
sed /./= /etc/fstab
示例
 
s/old/new/: 查找替换,替换old为new,其中/可以自定义,比如也可以写成[email protected]@@,s###等
替换标记:
g: 行内全局替换(s///g),即替换所有匹配到的字符串
p: 显示替换成功的行(s///p)
w FILE: 将替换成功的结果保存至文件中
i: 忽略字符大小写
&: 表示引用匹配到的内容
!: 取反条件
\w+ 匹配每一个单词
技术分享图片
# 查找文件sftab含有oot的行全部替换成OOT,默认只替换每行第一次被模式匹配到的串
sed s/oot/OOT/ /etc/fstab

# 查找文件fstab中,/开头的字符串,把/全部换成*sed s/^\//*/g /etc/fstab 表示

# 符合l..e模式的字符串,在后面添加一个er
sed [email protected]@&[email protected] /etc/fstab
sed s#\(l..e\)#\1er#g /etc/fstab

# 将每个单词使用方括号[]括起来
echo this is a test line | sed s/\w\+/[&]/g
"""
[this] [is] [a] [test] [line]
""‘

# 替换digit 76
echo this is digit 7 in number. | sed [email protected] \([0-9]\)@\[email protected]

# 查找/etc/fstab文件中,UUID和tmpfs之间的行,每行的行尾加上字符串aaa bbb
sed /UUID/,/tmpfs/[email protected][email protected] [email protected] /etc/fstab

# 查找line1到line2之间的所有aa bbb 替换为AA BBB
sed /line1/,/line2/[email protected] [email protected] [email protected] file_name

# 显示第一次匹配到的3,到最后一行输出
sed -n /3/,$p file_name

# 显示第一次匹配到的3,到向下2行输出
sed -n /3/,+2p file_name
示例
:
所有的处理命令均是在sed自己的模式空间内操作
要想同步修改目标文件内容,需要加上-i选项
 

练习题

技术分享图片
# 删除/boot/grub/grub.conf文件中所有以空白开头的行的行首的空白字符
sed s#^[[:space:]]\+## /boot/grub/grub.confsed

# 删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
sed [email protected]^#[[:space:]]\[email protected]@ /etc/fstab

# echo一个绝对路径给sed命令,取出其基名,取出其目录名
echo /etc/sysconfig/network | sed [email protected][^/]\+/\[email protected]@

# 删除文件/etc/init.d/inittab中所有的数字
sed s/[[:digit:]]\+//g /etc/init.d/inittab

# 将时间格式 yy/mm/dd 的日期格式换成 yy:mm:dd的格式
date +"%Y/%m/%d" |sed -n s#/#:#gp

# 显示奇数行
sed -n 1~2p file_name

# 显示偶数行
sed -n 2~2p file_name

# 删除模式一到模式二匹配到的行
sed /^aaa/,/^eee/d file_name

# 从指定行开始开始,每隔2行显示一次
sed -n 2,${p;n;n} file_name

# 删除一个文件中所有的数字
sed s/[[:digit:]]\+//g /etc/init.d/inittab

# 将时间格式 yy/mm/dd 的日期格式换成 yy:mm:dd的格式
date +"%Y/%m/%d" |sed -n s#/#:#gp

# 显示奇数行
sed -n 1~2p file

# 删除模式一到模式二匹配到的行
sed /^aaa/,/^eee/d File

# 从指定行开始开始,每隔2行显示一次
sed -n 2,${p;n;n} File

# 删除文中的最后两行
sed N;$!P;$!D;$d /etc/passwd

# 删除文中的空行
sed /./!d /etc/fstab

# 每隔5行增加一个空行
sed n;n;n;n;G; File

# 不显示指定字符开始的行
sed -n /^aaa\+/!p File

# 查找文件中1到20行之间,同时将”aaa”替换为”AAA” ,”ddd”替换”DDD”
sed -nr s/(.*)([^a-Z]+)([a-Z]+)([^a-Z]*)/\1\2\4/p /etc/passwd

# 替换文本中的字符串
echo "sksksksksksk" | sed s/sk/SK/3g
练习1
技术分享图片
cat test
"""
1 nimgtw         48003/udp               # Nimbus Gateway
2 3gpp-cbsp       48049/tcp               # 3GPP Cell Broadcast Service Protocol
3 isnetserv       48128/tcp               # Image Systems Network Services
4 isnetserv       48128/udp               # Image Systems Network Services
5 blp5           48129/tcp               # Bloomberg locator
6 blp5           48129/udp               # Bloomberg locator
7 com-bardac-dw     48556/tcp               # com-bardac-dw
8 com-bardac-dw     48556/udp               # com-bardac-dw
9 iqobject        48619/tcp               # iqobject
10 iqobject        48619/udp               # iqobject
"""

# 打印匹配blp5开头的行
sed -n /^blp5/p test

# 打印出第一行
sed -n 1p test

# 打印出第1行到第3行
sed -n 1,3p

# 打印出奇数行
sed -n 1~2p test

# 打印出偶数行
sed -n 2~2p test

# 打印匹配的行和它后面的一行
sed -n /nimgtw/,+1p test

# 打印最后一行
sed -n $p test

# 打印所有行,除了最后一行
sed -n $!p test

# 匹配范围
sed -n /^blp5/,/^com/p test

# 匹配开头行到最后一行
sed -n /^blp5/,$p test

# 引用变量,来匹配行
a = 1
sed -n ‘‘$a,3p test
# 注意:sed后面跟单引号,变量需要单引号才能引用,sed后面用双引号,变量则无需引号也会被引用

# 匹配删除
sed /blp5/d test

# 匹配删除奇数行
sed 1~2d test

# 匹配删除第1行到第3行
sed 1,3d test

# 替换blp5为test
sed s/blp5/test/g test

# 替换开头是blp5的行并打印
sed -n s/^blp5/test/p test

# 引用匹配内容并替换
sed s/^blp5/&00000000/ test

# ip加单引号
echo 10.10.10.1 10.10.10.2 10.10.10.3 | sed -r s/[^ ]+/"&"/g

# 对1-5行的blp5进行替换
sed 1,5s/blp5/test/ test

# 对匹配行进行替换,查找tcp且开头是com的行,替换成COM
sed /tcp/s/^com/COM/ test

# 多次匹配并替换
sed s/blp5/test/;s/3g/4g/ test

# 将协议与端口号位置调换(不明白)
sed -r s/(.*)(\<[0-9]+\>)\/(tcp|udp)(.*)/\1\3\/\2\4/ test

# 注释掉匹配行后面的指定行数
seq 10 | sed /5/,+3s/^/#/
练习2
技术分享图片
# 将 error.log中匹配到的内容保存至某个文件中:
sed -n /root/w file.txt error.log

# 将文件中的内容读入到匹配的内容后面
sed /root/r abc.txt /etc/passwd

# 打印匹配到的内容,并显示行号
sed -n /root/{=;p} /etc/passwd

# 删除匹配到的行的下一行
sed -n /UUID/{n;d} /etc/fstab

# 删除匹配到的行和下一行
sed /UUID/{N;d} /etc/fstab

# 删除文件每行中的第一个字符
sed -n s/^.//gp /etc/fstab

# 删除文件每行的第二个字符
sed -nr s/(.)(.)(.*)/\1\3/p /etc/passwd

# 删除文件每行的最后一个字符
sed -nr s/.$//p /etc/passwd

# 删除每行的最后一个单词
sed -nr s/(.*)([^a-Z]+)([a-Z]+)([^a-Z]*)/\1\2\4/p /etc/passwd

# 将file文件中的内容,实现最终效果,如下:
cat file
"""
aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
"""
# 实现如下效果:
cat file
"""
aaa bbb
ccc ddd
eee fff
ggg hhh
"""

# 实现方法
sed N;s/\n/\t/ b.tx

# 实现原理:
# N:读取下一行并追加到模式空间中的行后面,当Sed读入第一行内容时,由N将下一行的内容追加到模式空间中,此时模式空间的内容为“aaa\nbbb”,再由编写的匹配规则进行替换将”\n”替换为了”\t”,再执行默认的”p”操作,输出到标准输出
练习3

 

以上是关于三剑客之sed的主要内容,如果未能解决你的问题,请参考以下文章

linux文本三剑客之sed命令详解

三剑客之sed

三剑客之SED行天下

文本处理三剑客之 sed

三剑客之sed

linux三剑客之sed入门详解