sed命令

sed命令

简介:

sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。

​ sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下: 首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件,除非使用 -i 选项会修改原文件。

sed 有两个内置的存储空间:

​ 模式空间:模式空间用于 sed 命令执行的正常流程中。该空间 是sed 命令内置的一个缓冲区,用来存放、修改从输入文件读取的内容。

​ 保持空间: 保持空间是另外一个缓冲区,用来存放临时数据。Sed 命令可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。每次循环读取数据过程中,模式空间的内容都会被清空,然而保持空间的内容则保持不变,不会在循环中被删除。

sed命令有两个内置的存储空间:

名称概念
模式空间(pattern space)模式空间用于 sed命令 执行的正常流程中。该空间是sed命令内置的一个缓冲区,用来存放、修改从输入文件读取的内容。
保持空间 (hold space)保持空间是另外一个缓冲区,用来存放临时数据。Sed命令可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。

相关选项:

n 输出模式空间行,读取下一行替换当前模式空间的行,执行下一条处理命令而非第一条命令。
N 读入下一行,追加到模式空间行,此时模式空间有两行内容。
h 把模式空间里的行复制到保持空间。
H 把模式空间里的行追加到保持空间。
g 用保持空间的内容替换模式空间的行。
G 把保持空间的内容追加到模式空间的行后面。
x 将保持空间的内容与模式空间里的当前行互换。
!对所选行以外的所有行应用命令。保持空间里默认存储一个空行。

可能应用于

  • 处理多行模式空间( N、D、 P )
  • 采用保持空间来保存模式空间的内容并使它可用于后续的命令 ( H、h、G、g、x)
  • 编写使用分支和条件指令的脚本来更改控制流( :、b、t )
演示
N : 多行命令

多行Next (N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后来创建多行模式空间。模式空间最初的内容和新的输入行之间用换行符分隔。在模式空间中嵌入的换行符可以利用转义序列“\n”来匹配。在多行模式空间中,元字符“^”匹配空间中的第一个字条,而不匹配换行符后面的字符。同样,“$”只匹配模式空间中最后的换行符,而不匹配任何嵌入的换行符。在执行next命令之后,控制将被传递给脚本中的后续命令。

Next命令与next命令不同,next 输出模式空间的内容,然后读取新的输入行。next 命令不创建多行模式空间。

[root@localhost ~]# cat test    
good morning
good noon
Good eve          # 使用N命令前
ning
good night

[root@localhost ~]# sed '/Good/{N;s/\n//}' test 
good morning
good noon
Good evening     # 使用N命令输出后
good night

上面这个演示,用sed命令匹配到Good这行的文本在使用N将匹配到文本和下一行加入到模式空间,然后使用替换命令将换行符替换为空,结果就是在文件中的不完整的两行合并成了完整的一行。

delete: 删除命令

当遇到一个空行时,下一行就追加到模式空间中。然后试着匹配嵌入的换行符。注意定位元字符^和$分别匹配模式空间的开始处和结束处。

[root@localhost ~]# cat -n test  # 原文件
1  good morning
2  
3  good noon
4  
5  
6  Good evening
7  
8  
9  
10 good night

[root@localhost ~]# sed '/^$/{N;/^\n$/d}' test  # 使用d 命令输出结果 
1  good morning
2
3  good noon
4  Good evening
5 
6  good night

​ d 命令是当有偶数个空行时,所有的空行都会被删除。仅当有奇数个空行时,有一行被保留下来。这是因为删除命令清除的是整个模式空间。一旦遇到第一个空行,就读入下一行,并且两行都被删除。如果遇到第三个空行,并且下一行不为空,那么删除命令就不会被执行,因此空行被输出。

Delete : 多行删除命令

​ 删除命令 d 删除模式空间的内容并会读入新的输入行,从而在脚本的顶端重新使用编辑方法。删除命令D 有些不同: 删除模式空间中直到第一个嵌入的换行符的这部分内容。它不会读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用于模式空间剩余的内容,我们可以编写一个实现查找一系列空行并输出单个空行的脚本。

[root@localhost ~]# cat -n test  # 原文件
1  good morning
2  
3  good noon
4  
5  
6  Good evening
7  
8  
9  
10 good night

[root@localhost ~]# sed '/^$/{N;/^\n$/D}' test 
1  good morning
2
3  good noon
4
5  Good evening
6
7  good night

​ 多行D 命令完成工作的原理是: 当遇到两个空行时,D 命令只删除两个空行中的第一个。下一次读取该脚本时,这个空行会被另一行读入模式空间。如果那行不为空,那么两行都输出,因此确保了输出一个空行。说白点就是,当模式空间中有两个空行时,只有第一个空行被删除,当一个空行后面跟有文本时,不对模式空间里的内容处理。
在这里插入图片描述

h: 将模式空间的内容复制到保持空间

H: 将模式空间的内容追加到保持空间

g: 将保持空间的内容复制到模式空间

G: 将保持空间的内容追加到模式空间

x: 把保持空间的内容和模式空间的内容进行交换
在这里插入图片描述

h,H,g,G使用:
[root@localhost ~]# cat test    # 原文件
aaa
AAA
aaa
AAA

[root@localhost ~]# sed '/aaa/{h;d};/AAA/{G}' test    #使用sed命令处理后
AAA
aaa
AAA
aaa

​ 原文件是小写a在前面,通过sed命令(h)和(G)处理后,它们的位置调换了。如何实现的呢?:我们将第一行复制到保持空间(h),然后我们清除模式空间(d),然后sed将第二行读入模式空间,并且将保持空间的行追加(G)到模式空间的结尾,就有了处理后的结果。

b 分支命令

​ 通常,sed 程序的执行过程会从第一个脚本命令开始,一直执行到最后一个脚本命令(D 命令是个例外,它会强制 sed 返回到脚本的顶部,而不读取新的行)。sed 提供了 b 分支命令来改变命令脚本的执行流程,其结果与结构化编程类似。

b 分支命令基本格式为:

[address]b [label]

其中,address 参数决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。

需要注意的是,如果没有加 label 参数,跳转命令会跳转到脚本的结尾:

[root@localhost ~]# cat test
this is the first data line
this is the second data line
this is the header line
this is the last line

[root@localhost ~]# sed '{2,3b ; s/this is/Is this/ ; s/line/test/}' test
1 Is this the header test
2 this is the first data line
3 this is the second data line
4 Is this the last test

​ 可以看到,上面例子中因为 b 命令未指定 label 参数,因此数据流中的第2行和第3行并没有执行那两个替换命令。

​ 如果我们不想直接跳到脚本的结尾,可以为 b 命令指定一个标签(也就是格式中的 label,最多为 7 个字符长度)。在使用此该标签时,要以冒号开始(比如 :label2),并将其放到要跳过的脚本命令之后。这样,当 sed 命令匹配并处理该行文本时,会跳过标签之前所有的脚本命令,但会执行标签之后的脚本命令。

[root@localhost ~]# sed '{/first/b hello1 ; s/this is the/hello world to/
> :hello1
> s/this is the/Jump here on/}' test
hello world to header line
Jump here on first data line
hello world second data line
hello world last line

​ 在上面这个例子中,如果文本行中出现了 first,程序的执行会直接跳到 hello1 标签之后的脚本行。如果分支命令的模式没有匹配,sed 会继续执行所有的脚本命令。

[root@master ~]# echo "This, is, a, test, to, remove, commas." | sed -n '{
> :start
> s/,//1p
> /,/b start
> }'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.

b 分支命令除了可以向后跳转,还可以向前跳转,例如:在这个例子中,当缓冲区中的行内容中有逗号时,脚本命令就会一直循环执行,每次迭代都会删除文本中的第一个逗号,并打印字符串,直至内容中没有逗号为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值