一、简介
Sed命令是一个功能强大的流文件处理器,可用于从文件中读取数据,或从标准输入中读取数据进行处理。
Sed命令的空间概念
对于Sed命令的来说,要想能够灵活使用sed命令,就得将Sed命令的两个概念理解透,其分别为:模式空间(pattern space)和保持空间(hold space)。
模式空间:为Sed命令在处理数据流的特殊区域,Sed命令会将每一行的数据读取到模块空间中进行处理;
保持空间:类似于数据仓库,常用于暂存数据仓库;
模式空间及保持空间的工作原理示意图:
二、Sed命令的使用
1、命令
sed [OPTION]... {script} [input-file]...
2、选项
-n:不输出模式空间中的内容到屏幕;
-e script:能同时定制多个编辑命令脚本,每个脚本前带-e;
-f /PATH/TO/SCRIPT_FILE:指定script来源文件,文件中一行为一个script;
-r,--regexp-extended:支持扩展正则表达式;
-i[SUFFIX]:直接编辑源文件;
3、Sed命令的script
script的地址定界
通常来说script地址定界的使用格式类似于:1,3s/crontabtest/mylinux/g
其中1,3表示读取的数据流的第一行到第三行;
地址定界的格式通常由下列几种:
1)地址为空,表示针对全文作处理;
2)使用单个数字#,表示某行;
3)可使用/PATTERN/模式匹配相应的行;
4)范围指定,可使用,
分隔地址的起始行,如1,3表示从第一行到第三行;1,+3表示从第一行到第四行;也可以使用模式进行范围指定,如1,/mylinux/表示第一行到匹配到的第一个mylinux的行为止;或者直接使用/pattern/,/pattern/指定起始范围。
5)指定步长,如1~2
,指所有奇数行;2~2
,指所有的偶数行;
6)$指定最后一行。脚本指令
脚本指令用于指定sed命令的功能,如替换、删除、追加等。
常用的脚本指令有:
指令 | 功能 |
---|---|
s | 替换,如:s/mylinux/test/g |
a\ | 在下面追加新的行,如:1,3a\newline |
c\ | 将指定行更改为对应的字符串,如:1c\crontabtest2123 |
y | 按字符转换,指定指定的字符内容替换为对应的替换字符,两者的字符长度需一致,如:1,3y/cron/yese/ |
p | 打印,通常与选项-n一起操作 |
w | 保存至文件 |
d | 删除指定的行 |
i\ | 在行上面插入新的行,如,1i\handwell |
l | 打印(显示非打印字符) |
L | 打印(不显示非打印字符) |
r | 读入文件内容 |
q | 退出 |
- 修饰符
修饰符 | 功能 |
---|---|
g | 表示全行替换,通过加在script的末尾,可用Ng表示只替换每行的前N个 |
p | 表示打印行 |
w | 表示把行写入到一个文件 |
x | 交换模式空间和保持空间的内容 |
\N | 子串匹配标记,N表示匹配的第N个\(...\)里面的内容 |
& | 表示此前已匹配的字符串标记 |
- Sed命令的高级指令
高级指令 | 功能 |
---|---|
n或N | 读取或追加当前输入行的下一行到模式空间 |
h或H | 复制或追加模块空间内容到保持空间 |
g或G | 复制或追加保持空间内容到模式空间 |
D | 删除模式空间的内容直到第一行,如果模式空间中没有换行符,则其功能与d一样 |
- Sed命令的分隔符
默认Sed命令的分隔符为/
,通常表现的使用格式为s///g
之类的格式。但是有时候在匹配的Patten中有可能也会出现/
,此时在编写sed命令的时候就很容易出错。幸好Sed命令支持使用其他三个相同的符号作为分隔符,即sed 's/old/new/g'
可被替换为sed 's@old@new@g'
其中@
作为新的分隔符。
三、Sed命令的使用案例及解析
- 字符串替换
将文本第一行的jack字符串替换为相应的字符串:
[root@localhost ~]# sed s/jack/replacetext/g /tmp/sedtext
1replacetext
2charlie
3bob
4nancy
5john
6kobe
7wall
修饰符g表示会将每行中与匹配条件相符合的替换为指定的字符串,不带修饰符g默认只会替换每行匹配的第一个;
- 使用sed命令匹配到的字符串重复显示后输出:
[root@localhost ~]# sed 's/[[:alpha:]]\+/&&/' /tmp/sedtext
1jackjack
2charliecharlie
3bobbob
4nancynancy
5johnjohn
6kobekobe
7wallwall
上述sed命令使用了正则表达式匹配了相应的人名,并使用&调用前面匹配到的字符串进行重复输出,另外可以可以使用\1调用子串的方式实现:
[root@localhost ~]# sed 's/\([[:alpha:]]\+\)/\1\1/' /tmp/sedtext
1jackjack
2charliecharlie
3bobbob
4nancynancy
5johnjohn
6kobekobe
7wallwall
注意:\1是指匹配script脚本中从左往右的第一个()中的内容,以此类推的还有\2,\3等等。
- 追加一个行至指定位置
使用a指令可将给定的字符串追加到指定行的后面,如果没有指定地址,a指令默认作用于所有行;
[root@localhost ~]# sed '2a\newline' /tmp/sedtext
1jack
2charlie
newline
3bob
4nancy
5john
6kobe
7wall
使用i指令可在行上方插入:
[root@localhost ~]# sed '2i\newline' /tmp/sedtext
1jack
newline
2charlie
3bob
4nancy
5john
6kobe
7wall
- 删除指定的行
使用以数字开头的行:
[root@localhost ~]# sed '/^[[:digit:]]/d' /tmp/sedtext
apple
banana:22
purple:ant
删除1,5行:
[root@localhost ~]# sed '1,5d' /tmp/sedtext
6kobe
7wall
apple
banana:22
purple:ant
- 打印指定行
默认情况下在模式空间中处理完的数据会被输出到标准输出中,因此如果再次调用p指令,会发现指定的行重复出现了,如:
[root@localhost ~]# sed '2p;4,5p' /tmp/sedtext
1jack
2charlie
2charlie
3bob
4apple
4apple
hadoop56;
hadoop56;
linux12
john11alice
上述指定打印的2,4,5行便重复输出了,此时可使用-n选项,禁止默认模式空间内容输出:
[root@localhost ~]# sed -n '2p;4,5p' /tmp/sedtext
2charlie
4apple
hadoop56;
- 连续编辑-e
使用选项-e可以连续使用多个script编辑流:
[root@localhost ~]# sed -e 's/john/ubuntu/g' -e 's/^[[:digit:]]\([[:lower:]]\+\)/&\1/g' /tmp/sedtext
1jackjack
2charliecharlie
3bobbob
4appleapple
hadoop56;
linux12
ubuntu11alice
上述命令在使用-e选项john替换为ubuntun后,在用-e选项增加一个script将以数字开头的行后面的字符串重复一遍。
- 保存输出结果到指定文件
使用选项w可将sed命令匹配指定的接口保存到指定的文件路径:
[root@localhost ~]# sed -e 's/john/ubuntu/g' -e 's/^[[:digit:]]\([[:lower:]]\+\)/&\1/g w /tmp/test' /tmp/sedtext
1jackjack
2charliecharlie
3bobbob
4appleapple
hadoop56;
linux12
ubuntu11alice
[root@localhost ~]# cat /tmp/test
1jackjack
2charliecharlie
3bobbob
4appleapple