一、sed工具简介
sed是Linux下一款功能强大的非交互式文本编辑器,可以对文本文件进行增、删、改、查等操作,支持按行、按字段、按正则匹配文本内容,灵活方便,特别适合于大文件的编辑。sed在处理文本时是逐行读取文件内容,读到匹配的行就根据指令做操作,不匹配就跳过。
在处理文本时把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),紧接着用SED命令处理缓冲区中的内容,处理完成后把缓冲区的内容输出至屏幕或者写入文件。
逐行处理直到文件末尾,然而如果打印在屏幕上,实质文件内容并没有改变,除非使用重定向存储输出或者写入文件。
二、sed命令和选项
2.1 sed命令
命令 |
功 能 |
a |
在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行 |
c |
用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用"\"续行 |
i |
在当前行之前插入文本。多行时除最后一行外,每行末尾需用"\"续行 |
d |
删除行 |
h |
把模式空间里的内容复制到暂存缓冲区 |
H |
把模式空间里的内容追加到暂存缓冲区 |
g |
把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容 |
G |
把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面 |
l |
列出非打印字符 |
p |
打印行 |
n |
读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理 |
q |
结束或退出 sed |
r |
从文件中读取输入行 |
! |
对所选行以外的所有行应用命令 |
s |
用一个字符串替换另一个 |
g |
在行内进行全局替换 |
w |
将所选的行写入文件 |
x |
交换暂存缓冲区与模式空间的内容 |
y |
将字符替换为另一字符(不能对正则表达式使用 y 命令) |
2.2 sed选项
三、正则表达式元字符
sed支持特殊元字符,来进行模式查找、替换。不同的是,sed 使用的正则表达式是括在斜杠线"/"之间的模式。
元字符 |
功 能 |
示 例 |
^ |
首行定位符 |
/^my/ 匹配所有以 my 开头的行 |
$ |
行尾定位符 |
/my$/ 匹配所有以 my 结尾的行 |
. |
匹配除换行符以外的单个字符 |
/m..y/ 匹配包含字母 m,后跟两个任意字符,再跟 字母 y 的行 |
* |
匹配零个或多个前导字符 |
/my*/ 匹配包含字母 m,后跟零个或多个 y 字母的行 |
[] |
匹配指定字符组内的任一字符 |
/[Mm]y/ 匹配包含 My 或 my 的行 |
[^] |
匹配不在指定字符组内的任一字符 |
/[^Mm]y/ 匹配包含 y,但 y 之前的那个字符不是 M 或 m 的行 |
\(..\) |
保存已匹配的字符 |
1,20s/\(you\)self/\1r/ 标记元字符之间的模式, 并将其保存为标签 1,之后可以使用\1 来引用它。 最多可以定义 9 个标签,从左边开始编号,最左边 的是第一个。此例中,对第 1 到第 20 行进行处理, you 被保存为标签 1,如果发现 youself,则替换为 your。 |
& |
保存查找串以便在替换串中引用 |
s/my/**&**/ 符号&代表查找串。my 将被替换为 **my** |
\< |
词首定位符 |
/\<my/ 匹配包含以 my 开头的单词的行 |
\> |
词尾定位符 |
/my\>/ 匹配包含以 my 结尾的单词的行 |
x\{m\} |
连续 m 个 x |
/9\{5\}/ 匹配包含连续 5 个 9 的行 |
x\{m,\} |
至少 m 个 x |
/9\{5,\}/ 匹配包含至少连续 5 个 9 的行 |
x\{m,n\} |
至少 m 个,但不超过 n 个 x |
/9\{5,7\}/ 匹配包含连续 5 到 7 个 9 的行 |
例如:sed -n '\o^Myop' datafile
四、sed用法示例
4.1 增
#test内容 [root@localhost ruby]# cat test Hello! ruby is me,welcome to my blog. end #第一行后增加字符串"drink tea" [root@localhost ruby] # sed '1a drink tea' test Hello! drink tea ruby is me,welcome to my blog. end #第一行后增加多行,使用换行符\n [root@localhost ruby] # sed '1a drink tea\nor coffee' test Hello! drink tea or coffee ruby is me,welcome to my blog. end #在首行前插入一行内容 sed -i '1 s/^/容器ID,容器IP\n/' /tmp/docker_list.csv #在15行插入虚拟主机配置 sed '15 i\ include vhost/*;' nginx.conf #a在匹配行下一行添加字符,i表示在上一行添加字符 sed '/jfedu/aword' 1.txt |
4.2 删
#删除root到daemon的行 sed '/root/,/daemon/d' 1.txt #删除1到3行 sed '1,3d' 1.txt #删除匹配行的5行 sed '/wo/,5d' 1.txt #删除最后6行 for i in `seq 1 6`; do sed -i '$d' 1.txt;done #删除匹配行的注释 sed 's/^#\(shi\)/\1/' 1.txt #正则写法 sed '/^$/d' 1.txt sed -i /^[[:space:]]*$/d system.conf sed '/^#/d' 1.txt |
4.3 改
#表示在jfedu结尾添加字符 sed 's/jfedu$/& edu/g' 1.txt #给文件中的匹配行添加注释 sed 's/^wo/#&/' 1.txt #给文件中的匹配行添加注释 sed '/hello/s/^/&#/' 1.txt #给文件中的匹配行添加注释 sed -i 's/.*swap.*/#&/' /etc/fsttest 或 sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fsttest #给文件手动添加行号及结尾 sed -e '/hello/s/^/&1.' -e s/world$/&!/g 1.txt sed -e '/hello/s/^/&1./;s/world$/&!/g' 1.txt #使用定义的变量修改行内容 WEBSITE=HELLO WORLD sed 's/hello world/$WEBSITE/g' 1.txt #关闭selinux,重启系统生效 sed -i '/SELINUX/s/enforcing/distestled/g' /etc/selinux/config #合并上下两行内容 sed 'N;s/\n/ /' 1.txt # :a 在代码开始处设置一个标记a,在代码执行到结尾处时利用跳转命令t a重新跳转到标号a处,重新执行代码,这样就可以递归的将所有行合并成一行 sed ':a;N;s/\n/,/;t a;' 1.txt #第一行替换为Hi sed '1c Hi' test #第一行到第二行代替为Hi sed '1,2c Hi' test 替换一行中的某部分 #替换匹配行wo为ni sed 's/wo/ni/g' 1.txt #替换找到的第二个root为jfedu sed 's/root/jfedu/2' 1.txt #打印匹配的行,替换ruby为bird sed -n '/ruby/p' test | sed 's/ruby/bird/g' #\(...\)将捕获在parens内指定的字符,\1并将用于引用第一个匹配,这是正则表达式的一部分。 echo 'testctestctestc' | sed 's/\(test\)c/\1/' testtestctestc $ echo 'testctestctestc' | sed 's/\(test\)c/\1/g' testtesttest $ echo 'testctestctestc' | sed 's/\(test\)\(c\)/\1d\2/g' testdctestdctestdc 说明: 在第一个命令中,只有第一个匹配受到影响。在第二个命令中,每个匹配都会受到影响。在这两种情况下,\1指的是由转义括号捕获的字符。 在第三个命令中,指定了两个捕获组。他们通过使用\1和引用\2。最多可以使用九个捕获组。 #修改apache配置文件用户和组为apache sed -ri -e 's/^(User ).*/\1apache/' -e 's/^(Group ).*/\1apache/' /usr/local/apache/conf/httpd.conf 说明:-r 用来使用扩展正则表达式,此处不使用会报错! #开启apache中的ServerName指令(使用正则去掉#号) sed -ri 's/#(ServerName www.example.com:80)/\1/' /usr/local/apache/conf/httpd.conf |
4.4 查
#打印1-3行(只显示匹配的行) sed -n '1,3p' 1.txt #打印第一行与最后一行 sed -n '1p;$p' 1.txt #查询匹配的字符所在行 sed -n '/ruby/p' test |

