概述

  sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
  可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围。范围可以通过数据,正则表达式或者二者结合的方式确定。它可删除(delete)、改变(change)、添加(append)、插入(insert)、合、交换文件中的资料行,或读入其它档的资料到文 >件中,也可替换(substuite)它们其中的字串、或转换(tranfer)其中的字母……
注意
  1、sed总是以行对输入进行处理
  2、sed处理的不是原文件而是原文件的拷贝
  3、要灵活使用地址加指令:熟练运用指令中位址参数和指令与指令间的配合,可以完成非凡任务。


sed GUN 首页  本文基于sed版本:sed version 4.2.1


工作原理

  sed不是在原输入上直接进行处理的,而是先将读入的行放到缓冲区中,对缓冲区里的内容进行处理,处理完毕后也不会写回原文件(除非用shell的输出重定向来保存结果),而是直接输出到屏幕上。sed运行过程中维护着两个缓冲区,一个是活动的“模式空间(pattern space)”,另一个是起辅助作用的“暂存缓冲区(holding space)”。一般情况下,每当运行sed,sed首先把第一行装入模式空间,进行处理后输出到屏幕,然后将第二行装入模式空间替换掉模式空间里原来的内容,然后进行处理,以此类推。一般情况下暂存缓冲区是用不到的,但有特殊的命令可以在模式空间与暂存缓冲区之间交换数据,后文将有介绍。由于sed对文本的所有操作都是在缓冲区里进行的,所以不会对原文件造成任何破坏
简单表达:
  sed执行模板=sed ‘模式{命令1;命令2}’
  即逐行读入模式空间,执行命令,最后输出打印出来

语法

sed [OPTION]... {script-only-if-no-other-script} [input-file]...

通俗地讲sed编辑指令格式如下

[add1[,add2]]fun[arg]

其中 , 位址参数 add1 、add2 为行数或 regular expression 字串 , 表示所执行编辑的资料行; 函数参数 fun[arg] 为 sed 的内定函数 , 表示执行的编辑动作。

选项

OptionsOptionsOptionsDetails
-n使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e直接在命令列模式上进行 sed 的动作编辑;允许多个命令同时顺序编辑
-f直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
- -follow-symlinks直接修改文件时软链接保持,硬链接将被破坏
-i直接修改读取的文件内容,而不是输出到终端。默认会破坏符号链接和硬链接,可以通过配置- -follow-symlinks和- -copy改变
-c- -copy在-i模式下通过重命名copy文件而不是直接修改,可以规避对符号链接和硬链接的破坏,最终编辑结果不是自动,很少使用的方式,- -follow-symlinks一种足矣,它即快有安全
-l N指明换行的长度
- -posix禁用所有GNU扩展
-rsed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-s将输入文件视为各个独立的文件而不是一个长的连续输入
-u从输入文件读取最少的数据,更频繁的刷新输出
- -help显示帮助并退出sed
- -version显示版本号并退出sed

如果没有显式提供-e,–expresssion,-f或者–file选项,第一个非选项的参数将被当成sed脚本,其余的所有参数都是输入文件名称;如果没有指定输入文件,sed将会从标准输入读取。

命令说明

sed的命令的已知的主要摘要。

0个地址+cmd

命令含义
: label为b命令和t命令做标记;label的作用类似C语言中的goto,先定义一个标签,然后在其他地方可以goto到标签代码的地方重新执行;
comment注释会在新行结束或者在一个-e脚本控制的片段的结尾结束
}右花括号,需要有{配对成{}

0个地址或者一个地址+cmd

命令含义
=打印当前行号.
a\在当前行的下面加入一行
i\在当前行的上面插入一行.
q [exit-code]立即退出sed脚本,不会处理该命令后面的任何命令,如auto-print没有被禁用,当前模式空间会被打印,exit-code是GNU扩展
Q [exit-code]立即退出sed脚本,不会处理命令后面的任何命令,exit-code是GNU扩展
r filename从文件中读取文本
R filenameAppend a line read from filename. Each invocation of the command reads a line from the file. this is a sed testa GNU extension.

地址区间+cmd

命令含义
{块的开始标识,以}结束在sed命令里一般指集合有相同位址参数的指令
b label建立 script file 内指令互相参考的位置;分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾
t label先执行一替换的编辑指令,如果s///成功替换完成则调至label;如果省略label,分支直接跳到脚本的最后;if分支,从上次输入开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾
T label先执行一替换的编辑指令,如果替换失败,则将编辑指令跳至:label 处执行,如果省略:label,分支直接调至脚本的最后;错误分支,从上一行输入开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾
c \以新的输入的文本内容替换匹配行文件内容
dd命令是删除当前模式空间内容(不在传至标准输出),并放弃之后的命令,并对新读取的内容,重头执行sed。
DD命令是删除当前模式空间开端至\n的内容(不在传至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed
h拷贝pattern space(模式空间)的内容到holding space(暂存缓冲区)。h命令是将当前模式空间中内容覆盖至保持空间
H追加pattern space(模式空间)的内容到holding space(暂存缓冲区)。。
g获得holding space(暂存缓冲区)中的内容,并替代当前pattern space(模式空间)中的文本。
G获得holding space(暂存缓冲区)中的内容,并追加到当前pattern space(模式空间)的后面。
x交换 hold space 与 pattern space 内容
l印出 l 资料中的 nonprinting character 用 ASCII 码 以的形式列出当前行。l宽度以“视觉上明确”的形式列出当前行,在宽度字符处断开。这是一个GNU扩展 List out the current line in a ‘‘visually unambiguous’’ form.l width List out the current line in a ‘‘visually unambiguous’’ form, breaking it at width characters. this is a sed testa GNU extension.
n读取下一个输入行到模式空间.n命令简单来说就是提前读取下一行,覆盖模式空间前一行(并没有删除,因此依然打印至标准输出),如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后的任何命令,并对新读取的内容,重头执行sed
N添加下一个输入行到模式空间.N命令简单来说就是追加下一行到模式空间,同时将两行看做一行,但是两行之间依然含有\n换行符,如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后任何命令,并对新读取的内容,重头执行sed。
pp打印当前模式空间内容,追加到默认输出之后
PP打印当前模式空间开端至\n的内容,并追加到默认输出之前,sed并不对每行末尾\n进行处理,但是对N命令追加的行间\n进行处理,因为此时sed将两行看做一行
s/regexp/replacement/替换字符串内容,使用频率比较高
w filename把当前模式空间中的内容写入到名为filename的文件中
W filename把当前模式空间中第一行的内容写入到名为filename的文件中,这是一个GNU扩展
y/source/dest/表示把一个字符翻译为另外的字符(但是不用于正则表达式)
!表示后面的命令对所有没有被选定的行发生作用。

地址

sed命令可以省略地址,此时sed命令会对所有在所有输入行上执行;若有一个地址,sed命令会在匹配的行上执行命令;再或者有两个地址,sed命令会在两个地址之间的所有行上执行,包括两个边界行,这两个地址需要用逗号隔开。第一个地址被接受,即使第二个地址在第一个之前也没有关系;若第二个地址是正则表达,则不会执行第一个地址匹配的行。
在地址(或者地址区间)之后,在命令之前,可以插入一个”!”,表示地址(或者地址区间)不匹配才执行命令。

地址类型支持

地址形式含义
数值用数值支出具体匹配的行
start~step从start行开始,每隔步长为step的行数执行命令
$匹配最后一行
/regexp/使用正则表达式匹配行.
\cregexpc使用正则表达式,c是任意字符(我理解为上面/regexp/的另外一种写法.
addr1,addr2地址区间,addr1/addr2都支持正则表达式
addr1,+N从addr1开始加后面的N行,如/test1/,+2表示从test1行下面再数两行,总共3行
addr1,~N从addr1开始到下一个N的倍数。比如/test1/,~4 表示从第一行开始,那下个4的倍数是4,所以等价于1,4;同理/test2/,~4 等价于2,4;再如/test7/,~4,下个4的倍数是8,所以等价7,8

实例

准备文件(每个实例是独立的,修改数据后会还原数据为以下内容)

lingyue@lingyue-vm:~/test$vim testSed.txt
this is a sed test1 a is 1
this is a sed test2 b is 2
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5

1、-i选项,直接修改目标文件,有风险建议重新定向

lingyue@lingyue-vm:~/test$sed -i 's/test/final/g' testSed.txt
lingyue@lingyue-vm:~/test$cat testSed.txt
this is a sed final1 a is 1
this is a sed final2 b is 2
this is a sed final3 c is 3
this is a sed final4 d is 4
this is a sed final5 e is 5

2、-e选项,允许多个编辑

lingyue@lingyue-vm:~/test$sed -e 's/test/final/g' -e 's/sed/S/g' testSed.txt
this is a S final1 a is 1
this is a S final2 b is 2
this is a S final3 c is 3
this is a S final4 d is 4
this is a S final5 e is 5

3、-n取消默认打印

lingyue@lingyue-vm:~/test$sed -n -e 's/test/final/g' -e 's/sed/S/g' testSed.txt

4、-f选项,制定sed文件

lingyue@lingyue-vm:~/test$vim s.sed
s/test/final/g
lingyue@lingyue-vm:~/test$sed -f s.sed testSed.txt
this is a sed final1 a is 1
this is a sed final2 b is 2
this is a sed final3 c is 3
this is a sed final4 d is 4
this is a sed final5 e is 5

5、s命令
sed ‘s/src/des/g’ file

lingyue@lingyue-vm:~/test$sed 's/test/final/g' testSed.txt
this is a sed final1 a is 1
this is a sed final2 b is 2
this is a sed final3 c is 3
this is a sed final4 d is 4
this is a sed final5 e is 5

配合-i选项可以直接修改文件或者使用重定向将修改后的结果放入新的文件

sed -i 's/test/final/g' file
sed 's/test/final/g' file >outFileName

更多示例(输出省略):

$ sed -n 's/test/final/p' testSed.txt   //(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成final,就打印它。
$ sed 's/test/&add/' testSed.txt   //&符号表示替换换字符串中被找到的部份。所有匹配test的都会被替换成它自已加add,变成testadd。
$ sed -n 's/\(test\)/\1er/p' testSed.txt   //test被标记为1,所有test会被替换成tester,而且替换的行会被打印出来。
$ sed 's#test#final#g' testSed.txt   //不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,"#"在这里是分隔符,代替了默认的"/"分隔符。表示把所有test替换成final。

6、d命令
输出我给省略了~~

lingyue@lingyue-vm:~/test$sed '2d' testSed.txt   //删除testSed.txt文件的第二行。
lingyue@lingyue-vm:~/test$sed '2,$d' testSed.txt   //删除testSed.txt文件的第二行到末尾所有行。
lingyue@lingyue-vm:~/test$sed '$d' testSed.txt   //删除testSed.txt文件的最后一行。
lingyue@lingyue-vm:~/test$sed '/test/'d testSed.txt   //删除testSed.txt文件所有包含test的行。

7、r命令,将文件中的内容读出来显示在匹配行下面
s.sed里的内容被读进来,显示在与test匹配的所有匹配行的下面

lingyue@lingyue-vm:~/test$sed '/test/r s.sed' testSed.txt
this is a sed test1 a is 1
s/test/final/g
this is a sed test2 b is 2
s/test/final/g
this is a sed test3 c is 3
s/test/final/g
this is a sed test4 d is 4
s/test/final/g
this is a sed test5 e is 5
s/test/final/g

8、w命令
在testSed.txt中所有包含test的行都被写入output.txt里

lingyue@lingyue-vm:~/test$sed -n '/test/w output.txt' testSed.txt
lingyue@lingyue-vm:~/test$cat output.txt
this is a sed test1 a is 1
this is a sed test2 b is 2
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5

9、选定行的范围

所有在模板test1和test3所确定的范围内的行都被打印。
lingyue@lingyue-vm:~/test$sed -n '/test1/,/test3/p' testSed.txt  
this is a sed test1 a is 1
this is a sed test2 b is 2
this is a sed test3 c is 3
打印从第3行开始到第一个包含以test5开始的行之间的所有行。
lingyue@lingyue-vm:~/test$sed -n '3,/test5/p' testSed.txt
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5
对于模板test1和test3之间的行,每行的末尾用字符串end替换。
lingyue@lingyue-vm:~/test$sed '/test1/,/test3/s/$/end/' testSed.txt
this is a sed test1 a is 1end
this is a sed test2 b is 2end
this is a sed test3 c is 3end
this is a sed test4 d is 4
this is a sed test5 e is 5

9、i命令
在匹配的行上面插入新的文本(斜杠也可以省略)

lingyue@lingyue-vm:~/test$sed '/test1/i\insertnewchar' testSed.txt
insertnewchar
this is a sed test1 a is 1
this is a sed test2 b is 2
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5

10、a命令
在匹配的行下面插入新的文本(斜杠也可以省略)

lingyue@lingyue-vm:~/test$sed '/test1/a\insertnewchar' testSed.txt
this is a sed test1 a is 1
insertnewchar
this is a sed test2 b is 2
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5

11、c命令

行替换
lingyue@lingyue-vm:~/test$sed -e '1c\changed' testSed.txt
changed
this is a sed test2 b is 2
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5
字符替换
lingyue@lingyue-vm:~/test$sed -e 's/test1/&changed/' testSed.txt
this is a sed testchanged1 a is 1
this is a sed test2 b is 2
this is a sed test3 c is 3
this is a sed test4 d is 4
this is a sed test5 e is 5

12、n命令读取偶数行

lingyue@lingyue-vm:~/test$sed -n 'n;p' testSed.txt    
this is a sed test2 b is 2  
this is a sed test4 d is 4

解释:-n选项表示静默输出,即隐藏默认输出内容;读取第1行,执行n命令,此时模式空间为第2行,执行p,打印模式空间内容第2行内容,之后读取第3行,执行n命令,此时模式空间为第4行,执行p,打印模式空间内容第4行内容,之后读取第5行,执行n 命令,因为没有了,所以退出,并放弃p命令。

注意:还记不记得地址有一种写法:start~step,不清楚就往前翻找解释。

sed -n '2~2p' testSed.txt

13、N命令打印奇数行

lingyue@lingyue-vm:~/test$sed -n '$!N;P' testSed.txt            
this is a sed test1 a is 1
this is a sed test3 c is 3   
this is a sed test5 e is 5

注释:读取第1行,$!条件满足(不是尾行),执行N命令,得出”第1行内容\n第2行内容”,执行P,打印得第1行内容,读取第3行,$!条件满足(不是尾行),执行N命令,得出”第3行内容\n第4行内容”,执行P,打印得第3行内容,读取第5行,$!条件不满足,跳过N,执行P,打印得第5行内容
注意:同例12

sed -n '1~2p' testSed.txt

14、d命令

lingyue@lingyue-vm:~/test$sed 'n;d' testSed.txt           
this is a sed test1 a is 1
this is a sed test3 c is 3   
this is a sed test5 e is 5

注释:读取第1行,执行n,得出第2行内容,执行d,删除第2行内容,得空,以此类推,读取第3行,执行n,得出第4行内容,执行d,删除第4行内容,得空,但是读取第5行时,因为n无法执行,所以d不执行。因无-n参数,故输出”第1行内容\n第3行内容\n第5行内容”
15、D命令

lingyue@lingyue-vm:~/test$sed 'N;D' testSed.txt           
this is a sed test5 e is 5

注释:读取第1行,执行N,得出”第1行内容\n第2行内容”,执行D,得出第2行,执行N,得出”第2行内容\n第3行内容”,执行D,得出第3行,依此类推,得出第5行,执行N,条件失败退出,因无-n参数,故输出第5行
16、y命令替换字符

lingyue@lingyue-vm:~/test$sed 'y/es/ES/' testSed.txt  
thiS iS a SEd tESt1 a iS 1
thiS iS a SEd tESt2 b iS 2
thiS iS a SEd tESt3 c iS 3
thiS iS a SEd tESt4 d iS 4
thiS iS a SEd tESt5 E iS 5
lingyue@lingyue-vm:~/test$sed 's/\b[a-z]\b/\u&/g' testSed.txt  
this is A sed test1 A is 1
this is A sed test2 B is 2
this is A sed test3 C is 3
this is A sed test4 D is 4
this is A sed test5 E is 5

17、h命令,H命令,g命令,G命令
将testSed.txt文件中and前后数字和字母互换,并将字母大写

lingyue@lingyue-vm:~/test$cat sedScript.sed
h  
{  
s/.* test[0-9] \(.*\) is.*/\1/  
y/abcde/ABCDE/
G  
s/\(.*\)\n\(.*test[0-9] \).*\(is \)\(.*\)/\2 \4 \3 \1/  
}  
lingyue@lingyue-vm:~/test$sed -f sedScript.sed testSed.txt
this is a sed test1 1 is A
this is a sed test2 2 is B
this is a sed test3 3 is C
this is a sed test4 4 is D
this is a sed test5 5 is E

我简单解释下这个例子:s/.* test[0-9] (.*) is.*/\1/ 将字母列取出;然后使用y执行元字符替换;执行G,追加保持空间内容到模式空间,得A\nthis is a sed test1 a is 1;执行s,重新排列,得出this is a sed test1 1 is A;逐行处理。

保持和互换:h命令和x命令

互换模式空间和保持缓冲区的内容
lingyue@lingyue-vm:~/test$sed -e '/test1/h' -e '/test3/x' testSed.txt
this is a sed test1 a is 1
this is a sed test2 b is 2
this is a sed test1 a is 1
this is a sed test4 d is 4
this is a sed test5 e is 5

看匹配的test3的变化……

附录

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/(test)able/\1rs,testable被替换成testrs。
&保存搜索字符用来替换其他字符,如s/test/&/,test这成test
\<匹配单词的开始,如:/|匹配单词的结束,如/test
\>匹配包含以test结尾的单词的行。
x{m}重复字符x,m次,如:/0{5}/匹配包含5个0的行。
x{m,}重复字符x,至少m次,如:/0{5,}/匹配至少有5个0的行。
x{m,n}重复字符x,至少m次,不多于n次,如:/0{5,10}/匹配5~10个0的行。



原文链接

欢迎拍砖,未完待续……

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐