Linux命令学习-sed命令

176 阅读6分钟

sed是什么

sed是Linux下一款功能强大的非交互流式文本编辑命令,可以对文本文件进行增、删、改、查等操作,支持按行、按字段、按正则匹配文本内容,特别适合于大文件的编辑。本文主要介绍sed的演示sed的命令格式、常用命令和脚本操作等。

sed命令格式

使用man sed命令可以查看到,sed命令格式如下所示:

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

sed的常用选项:

-r:使用扩展正则表达式

-e script, --expression=script:它告诉sed将下一个参数解释为一个sed指令,只有当命令行上给出多个sed指令时才需要使用-e选项

-f, script-file, --file=script-file:后跟保存了sed指令的文件

sed SCRIPT

sed 命令的核心, SCRIPT由一系列的sed commands(sed命令)组成,使用-e,-f等选项将一系列的sed命令添加到脚本当中。在循环处理的过程中,对模式空间的内容使用脚本进行处理作为结果。

-i[SUFFIX], --in-place[=SUFFIX]:直接对内容进行修改,不加-i时默认只是预览,不会对文件做实际修改,当然,SUFFIX是可选的,如果加入SUFFIX,就会在改动原文件之前会将其以SUFFIX为文件名后缀备份一份。例如sed -i".bak" test.txt会在处理前将test.txt备份为test.txt.bak

-n, --quiet, --silent:取消默认输出,sed默认会输出所有文本内容,使用-n参数后只显示处理过的

请注意: 如果没有 -e,--expression, -f 或者 --file 选项,第一个非选项参数或作为sed script解释,所有剩下的参数都认为是输入的文件名称,如果没有指定输入文件名称,那么sed命令会使用标准输入

Sed Command命令

[addr]X[options]

简单理解,它由定位 + 编辑命令组成,addr就是定位命令 addr

addr是一个可选的能否标识行的地址,可以是一个单独的方号、正则、行范围

  • 单独一个数字标识行号。
  • /^#hello/ 表示以#hello开头的行。
  • /X$/ 表示以X结尾的行。
  • $表示最后一行。
  • x,/pattern/,从第 x 行到与 pattern 匹配的所有行
  • x,y!,匹配不包括 第x行 至 第y行的行
  • /pattern/,x,从与 pattern 匹配的行到第 x 行间的所有行
  • 0,addr2,匹配从开始至addr2的行,仅GUN sed支持,5,7表示5-7行。
  • addr1,~N,匹配从addr1开始的N行,仅GUN sed支持
  • addr1,+N,匹配addr1和它后面的N行,仅GUN sed支持,5,+6 表示第5行和跟着第5行后面的6行

编辑命令

编辑命令只能针对addr匹配的行进行处理,常见的选项如下:

  • a :新增, [options]为要增加的内容,新增的内容为单独一行,在当前行的下方,如果需要增加多行,行与行之间使用\n分割。

  • c :取代, [options]为新的内容。

  • i :插入, [options]为要插入的内容,插入的内容为单独一行,在当前行的上方,同样可以使用\n实现插入多行。

  • d :删除, 不需要[options]。

  • p :列印,不需要[options],将当前模式空间的内容打印出来,通常与参数 sed -n配合使用。

  • s :取代,最复杂的一个命令,[options]为正则表达式/REGEXP/REPLACEMENT/[FLAGS],例如:s/old/new/g表示将old换为new,g表示进行全局替换,默认为替换第一处。/old/new/g为s的option。

    • REGEXP

      正则表达式,匹配的内容会被REPLACEMENT替换。

    • REPLACEMENT

      字符串,直接替换

      • \N N可以为1~9, 引用匹配分组的内容。
        sed -e 's/#(Port.+)/\1/g' /etc/ssh/sshd_config
        sed -r -e 's/#(Port.+)/\1/g' /etc/ssh/sshd_config
        上面的两行等价将以#PORT开始的行#去掉,使用-r选项能够避免使用()

      • & 引用整个匹配内容
        sed -e s/^Port/#&/g /etc/ssh/sshd_config
        匹配以Port开头的行,并在前面加上#。

      • \L 将后面的内容转为小写,直到遇到\U或\E结束

      • \l 将后面的一个字符转为小写

      • \U 将后面的内容转为大写,直到遇到\L或\E结束

      • \u 将后面的一个字符转为大写

      • \E 结束\L,\U的转换
        sed -r -e 's/(\b[^\s])/\u\1/g' /etc/ssh/sshd_config
        将所有单词首字母大写。

    • FLAGS

      • g 全局替换
      • p 打印
      • = 打印行号
  • y :转换,[options]为转换字典/src/dst/,将出现的每个src中的字符替换为dst中相应的字符,y/abc#/ABC%/a->A,b->B,c->C,#->%

  • q :退出,[options]为返回值,退出后直接结束输入流的处理。

  • {},命令组,组内命令用分号;分隔

sed命令例子

  1. 插入行 在第三行后面插入hello
guanwu@master:~/learnshell/sed$ cat 1.txt 
111
222
333
444
555
666
guanwu@master:~/learnshell/sed$ sed '3ahello'  1.txt 
111
222
333
hello
444
555
666
guanwu@master:~/learnshell/sed$ 

sed -e '/world$/a====new line====' test4.txt 在 world结尾的下一行添加====new line====

guanwu@master:~/learnshell/sed$ cat test4.txt 
4444444111
66666helloworld
hihihihih
gagagagaga
world hello 
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$ sed -e '/world$/a====new line====' test4.txt 
4444444111
66666helloworld
====new line====
hihihihih
gagagagaga
world hello 
c++ java hello world
====new line====
1 2 3 34 45
guanwu@master:~/learnshell/sed$ 

sed -e '/world$/i====new line====' test4.txt 在 world结尾的前一行添加====new line====

guanwu@master:~/learnshell/sed$ sed -e '/world$/i====new line====' test4.txt 
4444444111
====new line====
66666helloworld
hihihihih
gagagagaga
world hello 
====new line====
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$

在最后一行前插入 hello java

sed '$ihello java' test4.tx

guanwu@master:~/learnshell/sed$ sed '$ihello java' test4.txt 
4444444111
66666helloworld
hihihihih
gagagagaga
world hello 
c++ java hello world
hello java
1 2 3 34 45
  1. 删除 删除1~3行
guanwu@master:~/learnshell/sed$ sed  -e  '1,3d'  1.txt 
444
555
666

从第1行开始,每隔两行删除一行,删除奇数行

sed '1~2d' test4.txt

guanwu@master:~/learnshell/sed$ sed '1~2d' test4.txt 
66666helloworld
gagagagaga
c++ java hello world

删除删除空行可以使用命令 sed /^$/d

  1. 打印

sed -n -e '1,3p' .txt 打印1~3行

guanwu@master:~/learnshell/sed$ sed -n -e  '1,3p'  1.txt 
111
222
333

sed -n -e '/^abc/p;a newline' 打印abc开始的行,每行后面添加newline

guanwu@master:~/learnshell/sed$ cat 2.txt 
111
222
abc333
444
555
666
abc777
888
abc999
guanwu@master:~/learnshell/sed$ sed -n -e '/^abc/p;a newline' 2.txt
newline
newline
abc333
newline
newline
newline
newline
abc777
newline
newline
abc999
newline

打印匹配4的行

guanwu@master:~/learnshell/sed$ cat test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
world hello 
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$ sed -n '/4/p' test4.txt 
4444444111
1 2 3 34 45

打印文件的行号,和打印匹配的行号和内容

guanwu@master:~/learnshell/sed$ sed -n  '=' test4.txt 
1
2
3
4
5
6
7
guanwu@master:~/learnshell/sed$ sed -n '/gagaga/{=;p}'  test4.txt 
4
gagagagaga
guanwu@master:~/learnshell/sed$ 

打印 匹配444 到 匹配gaga的行

sed -n '/444/,/gaga/p' test4.txt

guanwu@master:~/learnshell/sed$ cat test4.txt
4444444111
66666helloworld
hihihihih
gagagagaga
world hello 
c++ java hello world
1 2 3 34 45
guanwu@master:~/learnshell/sed$ sed -n '/444/,/gaga/p'  test4.txt 
4444444111
66666helloworld
hihihihih
gagagagaga
  1. 替换

sed -e 's/^/#/g' 2.txt 在所有行前添加#符号

guanwu@master:~/learnshell/sed$ sed -e 's/^/#/g' 2.txt
#111
#222
#abc333
#444
#555
#666
#abc777
#888
#abc999

sed -e 's/^[^#]/#&/' sample.txt 在所有非#开头的行添加#符号,使用&符号是为了避免误删开头的字符,如果不加&,则会出现 #nclude<stdio.h>这样的结果

guanwu@master:~/learnshell/sed$ cat sample.txt 
include<stdio.h>
#include<other.h>
#include<test.h>
include<test2.h>
guanwu@master:~/learnshell/sed$ sed  's/^[^#]/#&/' sample.txt 
#include<stdio.h>
#include<other.h>
#include<test.h>
#include<test2.h>

sed -r 's/(.*)/\U\1/g' 3.txt 将字母全部转为大写

guanwu@master:~/learnshell/sed$ cat 3.txt 
abc
hello World
This is a nice day 
haha, i am Fine 
guanwu@master:~/learnshell/sed$ sed -r 's/(.*)/\U\1/g' 3.txt 
ABC
HELLO WORLD
THIS IS A NICE DAY 
HAHA, I AM FINE 

sed -r -e '/^#/d' sample.txt 删除以#开头的行

guanwu@master:~/learnshell/sed$ cat sample.txt 
include<stdio.h>
#include<other.h>
#include<test.h>
include<test2.h>
guanwu@master:~/learnshell/sed$ sed  -r -e  '/^#/d' sample.txt 
include<stdio.h>
include<test2.h>

将**#PasswordAuthentication yes** 去掉注释,并将yes改为no

sed -n -r -e 's/^.{0,1}(PasswordAuthentication ).{2,3}$/\1no/gp' sample.config

guanwu@master:~/learnshell/sed$ cat sample.config 
#PasswordAuthentication yes
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication, then enable this but set PasswordAuthentication

guanwu@master:~/learnshell/sed$ sed -n -r -e 's/^.{0,1}(PasswordAuthentication ).{2,3}$/\1no/gp' sample.config 
PasswordAuthentication no
guanwu@master:~/learnshell/sed$ 

在文件的每一行后面添加haha

sed 's/$/&'haha'/' test2.txt

guanwu@master:~/learnshell/sed$ sed 's/$/&'haha'/' test2.txt 
ddddhaha
eeeehaha
fffffhaha
gggghaha
dddddfhaha
helloworldhagagahaha
guanwu@master:~/learnshell/sed$ 
  1. 从文件中读取内容

sed  'r test1.txt'  test2.txt  #将文件test1.txt中的内容,读入test2.txt中,会在test2.txt中的每一行后都读入test1.txt的内容

guanwu@master:~/learnshell/sed$ cat test2.txt 
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ cat test1.txt 
aaa
bbb
ccc
guanwu@master:~/learnshell/sed$ cat test2.txt 
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ sed 'r test1.txt' test2.txt
dddd
aaa
bbb
ccc
eeee
aaa
bbb
ccc
fffff
aaa
bbb
ccc
gggg
aaa
bbb
ccc

在第二行后读入 test1.txt的内容

sed '2r test1.txt' test2.txt

guanwu@master:~/learnshell/sed$ sed '2r test1.txt' test2.txt 
dddd
eeee
aaa
bbb
ccc
fffff
gggg

匹配ddd后的行插入test1.txt的内容

guanwu@master:~/learnshell/sed$ sed '/ddd/r test1.txt' test2.txt 
dddd
aaa
bbb
ccc
eeee
fffff
gggg

最后一行插入test1.txt的内容

sed '$r test1.txt' test2.txt

guanwu@master:~/learnshell/sed$ sed '$r test1.txt' test2.txt 
dddd
eeee
fffff
gggg
aaa
bbb
ccc
guanwu@master:~/learnshell/sed$ 
  1. 向文件中写入内容 将test2.txt的内容写入到test3.txt中,没有test3.txt时,会自动创建
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ cat test3.txt 
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ 

将test2.txt的第二行写入test4.txt中

guanwu@master:~/learnshell/sed$ sed '2w test4.txt' test2.txt
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ cat test4.txt 
eeee
guanwu@master:~/learnshell/sed$ 

匹配ddd或fff的行写入 test6.txt中

guanwu@master:~/learnshell/sed$ cat test2.txt 
dddd
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ sed -n '/ddd\|fff/w test6.txt' test2.txt 
guanwu@master:~/learnshell/sed$ cat test6.txt 
dddd
fffff
guanwu@master:~/learnshell/sed$ 

匹配eee到结尾的行写入到test7.txt中

guanwu@master:~/learnshell/sed$ sed -n '/eee/,$w test7.txt' test2.txt 
guanwu@master:~/learnshell/sed$ cat test7.txt 
eeee
fffff
gggg
guanwu@master:~/learnshell/sed$ 

参考

www.jianshu.com/p/f487a3392…

zhuanlan.zhihu.com/p/145661854

blog.csdn.net/wdz306ling/…