sed详解

℡╲_俬逩灬. 提交于 2020-03-01 05:52:15


sed(Stream EDitor),是一种流编辑器,用于文本编辑

语法

sed [option] 'SCRIPTS' FILE...

SCRIPTS:[Address] [!]Command 命令地址对

SED工作流程

  1. 读取新的一行到模式空间,将“SCRIPTS”的第一个address匹配,如果符合则执行command
  2. 如果address符合则执行command,不符合取下一个地址命令对
  3. 直到所有的地址命令对应用完,输出模式空间的内容

选项

选项 功能
-f FILE 调用sed脚本处理文件
-n 抑制默认内容输出,常与p命令连用
-r 支持扩展元字符
-iSUFFIX 修改源文件,同时创建一个备份文件,备份文件名为源文件名SUFFIX

SCRIPS

格式:[Address] [!]Command: !不执行后面的命令

address:

  • 空地址:匹配所有行
  • $:匹配最后一行
  • N:匹配第N行
  • N~M:从N行开始,每隔M-1行匹配
  • N,M:匹配N到M行
  • /PATTREN/:正则匹配的行

Command:包括模式空间命令和保持空间命令

模式空间命令

模式空间:可以想成工程里面的流水线,数据之间在它上面进行处理。

  • d ,删除模式空间的内容
  • p , 打印模式空间的内容
  • s///FLAG , 替换搜索 FLAG:g全局搜索
  • a\string ,append,追加内容
  • i\string ,insert,插入内容
  • c\string ,change,替换内容
  • = , 打印行号
  • l ,打印内容包括控制字符
  • y// , 字符装换
  • n next ,读取下一行到模式空间
  • r FILE , read读取文件内容到指定行
  • w FILE , write保存指定行到文件
  • [line-address]q , quit退出
  • N ,读取下一行内容到模式空间,以\n拼接上一行内容
  • P ,P打印当前模式空间开端至\n的内容,并追加到默认输出之前
  • D ,删除模式空间上一行的内容,并继续执行命令

保持空间命令

保持空间:可以想象成仓库,我们在进行数据处理的时候,作为数据的暂存区域。

  • h/H ,hold,将模式空间的内容覆盖h(追加H)到保持空间
  • g/G ,get,将保持空间内容覆盖g(追加G)到模式空间
  • x ,exchange,交换两个空间的内容

sed使用实例

测试文件内容

[root@localhost tmp]# cat test.txt 
This is the header line.
This is the first data line.
This is the second data line.
This is the last data line.
1、打印: p 命令

命令 p 是打印命令,用于显示模式空间的内容。默认情况下, sed 把输入行打印在屏幕上,选项-n 用于取消默认打印操纵。当选项-n 和命令 p 同时出现时, sed 可打印选定的内容

例子1:打印2行的内容

[root@localhost tmp]# sed '2p' test.txt 
This is the header line.
This is the first data line.
This is the first data line.
This is the second data line.
This is the last data line.

说明:默认情况下, sed 把所有输入行都打印在标准输出上。如果在某一行匹配到 north, sed就把该行另外打印一遍。

例子2:打印匹配first的行,并抑制未选定行输出

[root@localhost tmp]# sed -n '/first/p' test.txt     
This is the first data line.

说明:默认情况下, sed 打印当前缓存区中的输入行。命令 p 指示 sed 将再次打印该行。选项-n 取消 sed 取消默认打印操作。选线-n 和命令配合使用,模式缓冲区内的输入行,只被打印一次。如果不指定-n 选项, sed 就会像上例中那样,打印出重复的行。如果指定了-n,则sed 只打印包含匹配first 的行。

2、删除: d 命令

命令 d 用于删除输入行。sed 先将输入行从文件复制到模式空间,然后对该行执行 sed命令,最后将模式空间的内容显示在屏幕上。如果发出的是命令 d,当前模式缓存区的输入行会被删除,不被显示。

例子3:删除3到最后一行

[root@localhost tmp]# sed  '3,$d' test.txt           
This is the header line.
This is the first data line.
3、替换: s 命令

命令 s 是替换命令。替换和取代文件中的文本可以通过 sed 中的 s 来实现, s 后包含在斜杠中的文本是正则表达式,后面跟着的是需要替换的文本。可以通过 g 标志对行进行全局替换

例子4

[root@localhost tmp]# sed 's/h/ee/' test.txt 
Teeis is the header line.
Teeis is the first data line.
Teeis is the second data line.
Teeis is the last data line.
[root@localhost tmp]# sed 's/h/ee/g' test.txt 
Teeis is teee eeeader line.
Teeis is teee first data line.
Teeis is teee second data line.
Teeis is teee last data line.

说明:s 命令用于替换。命令末端的 g 表示在行内全局替换;也就是说如果每一行里出现多个h,所有的

都会被替换为 ee。如果没有 g 命令,则只将每一行的第一 h替换为 ee。

例子5

[root@localhost tmp]# sed 's/the/&     /' test.txt      
This is the      header line.
This is the      first data line.
This is the      second data line.
This is the      last data line.

当“与”符号( &)用在替换串中时,&代表在查找串中匹配到的内容时。这个示例中所有the后面都被加上多个空白字符。

例子6

#为方便测试,此处创建一个新文件
[root@localhost tmp]# cat > test1 << EOF
> the 1 line
> the 2 line
> the 3 line
> the 4 line
> EOF
[root@localhost tmp]# sed -r 's/(^.*)(\b[0-9]\b)(.*$)/\2 \1\3/' test1 
1 the  line
2 the  line
3 the  line
4 the  line

说明:包含在圆括号里的模式作为标签保存在特定的寄存器中。替换串可以通过\1\2\3 来引用它们,表示匹配到的第1,2,3个分组。上述例子将匹配到的三个分组调换顺序

4、追加: a 命令

a 命令是追加命令,追加将新文本到文件中当前行(即读入模式的缓存区行)的后面。

例子7

[root@localhost tmp]# sed '$a suprise!' test.txt                        
This is the header line.
This is the first data line.
This is the second data line.
This is the last data line.
suprise!

说明:命令 a 用于追加。字符串 suprise!被加在最后一行行之后。如果要追加的内容超过一行,则除最后一行外,其他各行都必须以\n结尾。

5、插入:i命令

i 命令是插入命令,类似于 a 命令,但不是在当前行后增加文本,而是在当前行前面插入新的文本,即刚读入缓存区模式的行。

例子8

[root@localhost tmp]# sed '$i suprise!\nhhh' test.txt  
This is the header line.
This is the first data line.
This is the second data line.
suprise!
hhh
This is the last data line.

说明:命令 i 是插入命令。本例i 命令在最尾行的上方插入文本。

6、修改:c命令

c 命令是修改命令。 sed 使用该命令将已有的文本修改成新的文本。旧文本被覆盖。
例子9

[root@localhost tmp]# sed '/data/c test' test.txt 
This is the header line.
test
test
test

说明:c 命令是修改命令。该命令将完整地修改在模式空间的当前行。如果模式 data被匹配, c 命令将其后的文本替换包含 data 的行。

7、打印行号:=命令

=命令可以用于显示匹配行的行号

例子10

[root@localhost tmp]# sed -n '/data/=' test.txt 
2
3
4

说明:使用=时,如果模式 data被匹配, =命令将输出匹配到的行号。

8、打印(包括控制字符):l命令

例子11

[root@localhost tmp]# sed -n '/data/l' test.txt  
This is the first data line.$
This is the second data line.$
This is the last data line.$

说明:l命令能打印出非打印字符,例子中的$为末尾标志

9、字符转换:y命令

y 命令表示转换。该命令与 tr 命令相似,字符按照一对一的方式从左到右进行转换。例如 y/abc/ABC/,会把小写字母转换成大写字母, a–>A,b–>B,c–>C。

例子12

[root@localhost tmp]# sed 'y/this/name/' test.txt 
Tame me nae aeader lmne.
Tame me nae fmren dana lmne.
Tame me nae eecond dana lmne.
Tame me nae laen dana lmne.
10、读取下一行:n命令

n 命令表示下一条命令。 sed 使用该命令获取输入文件的下一行,并将其读入到模式缓冲区中,任何 sed 命令都将应用到匹配行,紧接着的下一行上。

例子13

[root@localhost tmp]# sed -n 'n;p' test.txt   
This is the first data line.
This is the last data line.

说明:例子实现了偶数行输出,如果要改成奇数行,则改为p;n

11、读取文件:r命令

r命令将读取的文件内容插入到匹配行的后面

例子14

[root@localhost tmp]# cat test.sed 
hello
world
[root@localhost tmp]# sed '2r test.sed' test.txt 
This is the header line.
This is the first data line.
hello
world
This is the second data line.
This is the last data line.
12、保存文件:w命令

w命令将匹配到的行的内容保存到文件中,会覆盖文件原有内容

例子15

[root@localhost tmp]# sed '2,4w test.sed' test.txt 
This is the header line.
This is the first data line.
This is the second data line.
This is the last data line.
[root@localhost tmp]# cat test.sed                 
This is the first data line.
This is the second data line.
This is the last data line.
13、退出:q命令

q 命令表示退出命令。该命令将导致 sed 程序退出,且不再进行其他的处理。

例子16

[root@localhost tmp]# sed '3q' test.txt       
This is the header line.
This is the first data line.
This is the second data line.

说明:使用q命令可达到和head命令相同的效果,sed是一行行读入,head是将整个文件读入内存再进行处理,所以在读大文件的情况下,推荐使用sed。

14、读取下一行以\n拼接上一行:N

例子17

[root@localhost tmp]# sed '1{N;d}' test.txt  
This is the second data line.
This is the last data line.

说明:匹配到第1行后,模式空间的内容为‘This is the header line.’,后执行N命令,读入下一行的内容,将其以\n拼接在第一行后面,此时模式空间内容为‘This is the header line.\nThis is the first data line.‘,最后执行d命令,删除当前模式空间内容,所有最终的输出结果不会包含1,2行,此命令相当于删除1,2行。

15、打印至\n的内容:P

P打印当前模式空间开端至\n的内容,并追加到默认输出之前

例子18

[root@localhost tmp]# sed  'N;P' test.txt   
This is the header line.
This is the header line.
This is the first data line.
This is the second data line.
This is the second data line.
This is the last data line.

说明:命令匹配到第一行后,N命令读取第二行内容以\n拼接在第一行后面,之后P命令打印\n前面的内容,也就是第一行;之后命令匹配下一行,也就是第三行,重复上述步骤。

16、删除上一行:D

D命令是删除当前模式空间开端至\n的内容(不在传至标准输出), 放弃之后的命令,但是对剩余模式空间重新执行sed。

例子19

[root@localhost tmp]# sed 'N;D' test.txt    
This is the last data line.

说明:先读取1,执行N,得出1\n2,执行D,得出2,执行N,得出2\n3,执行D,得出3, 依此类推,得出4,执行N,条件失败退出,输出4

17、保持空间命令:h/H,g/G,x

h命令是将当前模式空间中内容覆盖至保持空间, H命令是将当前模式空间中的内容追加至保持空间

g命令是将当前保持空间中内容覆盖至模式空间, G命令是将当前保持空间中的内容追加至模式空间

x命令是交换两个空间的内容

例子20:把多行用,拼接成1行

[root@localhost tmp]# cat > test2 <<EOF
> a
> b
> c
> d
> e
> f
> EOF
[root@localhost tmp]# sed 'H;${x;s/\n/,/g;s/^,//};$!d' test2
a,b,c,d,e,f

说明:读取第一行a,将其追加到保持空间,保持空间一开始为/n,追加后变成/na,之后读取第二行追加,保持空间为/na/nb,以此类推直到最后一行,保持空间的内容为/na/nb/nc/nd/ne/nf,之后对最后一行执行x命令,将保持空间的内容和模式空间互换,再对模式空间中的/na/nb/nc/nd/ne/nf进行替换,把/n替换为,,在把第一个,换为空,则实现了多行拼接。

例子21:将行反转输出

[root@localhost tmp]# sed -n '1!G;h;$p' test2
f
e
d
c
b
a

说明:第一行a覆盖到保持空间,后匹配第二行b,将保持空间的内容a追加到模式空间,此时模式空间内容为b/na,之后把b/na覆盖到保持空间,读取第三行c,把保持空间内容b/na追加到模式空间,模式空间变成c/nb/na,以此类推,直到最后一行才打印出来。

改变流

通常sed编辑器会从脚本的开头开始,一直执行到脚本的结尾,改变流即改变默认sed的工作流程。

1、分支 branch

分支命令的格式如下:[address]b [lable] 参数address确定了哪些行的数据会触发分支命令,lable定义了要跳转到的位置,如果不定义lable则默认调到脚本的结尾。

测试文件

[root@localhost tmp]# cat test.txt 
This is the header line.
This is the first data line.
This is the second data line.
This is the last data line.

例子1:

[root@localhost tmp]# sed '2,3b;s/This is/Is this/;s/line./test?/' test.txt 
Is this the header test?
This is the first data line.
This is the second data line.
Is this the last data test?

说明:此例没有定义label,默认调到脚本的结尾,也就是说,匹配到的行2,3没有执行任何处理命令

例子2:

[root@localhost tmp]# sed '/first/b jump1;s/This is/Is this/;:jump1;s/line./test?/' test.txt 
Is this the header test?
This is the first data test?
Is this the second data test?
Is this the last data test?

说明:此例用/first/b jump来匹配到含有first的行,并且跳转到lable定义处:jump,所以这一行只执行分支标签后的操作,而未匹配到的行执行前面和jump后面的操作。

特别注意:

如果分支命令的模式没有匹配,sed编辑器会继续执行脚本中的命令,包括分支标签后的命令!

2、测试 test

测试命令(t)[address]t [lable]类似于分支命令也可以用来改变sed编辑器脚本的执行流程,测试命令会根据替换命令的结果跳转到某个标签,而不是根据地址进行跳转。
例子

[root@localhost tmp]# echo "This, is , a, test, to, remove, coomas."  | sed ':start;s/,//; b start'
^C

说明:branch做的是无条件的跳转,不管上一个命令执行成功与否,它都会跳转到label所在的命令,此例相当于一个无限循环

[root@localhost tmp]# echo "This, is , a, test, to, remove, coomas."  | sed ':start;s/,//; t start'
This is  a test to remove coomas.

说明:test做的是有条件的循环,只有上个命令执行成功,才跳转到标签所在位置。

改变流的branch和test命令很强大,使用它也需要很好的理解和想象力。
于分支命令也可以用来改变sed编辑器脚本的执行流程,测试命令会根据替换命令的结果跳转到某个标签,而不是根据地址进行跳转。
例子

[root@localhost tmp]# echo "This, is , a, test, to, remove, coomas."  | sed ':start;s/,//; b start'
^C

说明:branch做的是无条件的跳转,不管上一个命令执行成功与否,它都会跳转到label所在的命令,此例相当于一个无限循环

[root@localhost tmp]# echo "This, is , a, test, to, remove, coomas."  | sed ':start;s/,//; t start'
This is  a test to remove coomas.

说明:test做的是有条件的循环,只有上个命令执行成功,才跳转到标签所在位置。

改变流的branch和test命令很强大,使用它也需要很好的理解和想象力。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!