模式空间:
就是读入行所在的缓存,sed对文本的处理就是在这个缓存里进行的。
正常情况下,sed 读入一行进入模式空间进行处理,处理:、b、t:在脚本中实现分支与条件结构。完成, 模式空间清楚该行, 然后读入新的一行,重复相同的处理 , 直至文档处理完毕。但有时希望模式空间被保留,以便下一次处理。
1. N, D, P 处理多行模式空间的问题
2. H、h、G、g、x:将模式空间的内容放入存储空间以便接下来的编辑;
3: :、b、t:在脚本中实现分支与条件结构。
多行模式空间的处理:
由于正则表达式是面向行的,因此,如若某个词组一不分位于某行的结尾,另外一部分又在下一行的开始,这个时候用grep等命令来处理就相当的困难。然而,借助于sed的多行命令N、D、P,却可以轻易地完成这个任务。
N 将下一行读入到模式空间。
存储空间:
在模式空间和存储空间中的内容可以通过一组命令互相拷贝:
命令 简写 功能
Hold h或H 将模式空间的内容拷贝或附加到存储空间
Get g或G 将存储空间的内容拷贝或附加到模式空间
Exchange x 交换模式空间和存储空间中的内容
命令的大小写的区别在于大写的命令是将源空间的内容附加到目标空间,而小写的命令则是用源空间的内容覆盖目标空间。值得注意的是,不管是Hold命令还是Get命令,都会在目的空间的原有内容之后加上一个换行符,然后才把源空间中的内容加到换行符的后面。
流程控制命令:
为了使使用者在书写sed脚本的时候真正的"自由",sed还允许在脚本中用":"设置记号,然后用"b"和"t"命令进行流程控制。顾名思义,"b"表示"branch","t"表示"test";前者就是分支命令,后者则是测试命令。
首先来看标签的各式是什么。这个标签放置在你希望流程所开始的地方,单独放一行,以冒号开始。冒号与变迁之间不允许有空格或者制表符,标签最后如果有空格的话,也会被认为是标签的一部分。
再来说b命令。它的格式是这样的:
[address]b[label]
它的含意是,如果满足address,则sed流程跟随标签跳转:如果标签指明的话,脚本首先假设这个标签在b命令以下的某行,然后转入该行执行相应的命令;如果这个标签不存在的话,控制流程就直接跳到脚本的末尾。否则继续执行后续的命令。
在某些情况下,b命令和!命令有些相似,但是!命令只能对紧挨它的{}中的内容起作用,而b命令则给予使用者足够的自由在sed脚本中选择哪些命令应该被执行,哪些命令不应该被执行。下面提供几种b命令的经典用法:
(1) 创建循环:
:top
command1
command2
/pattern/b top
command3
(2) 忽略某些不满足条件的命令:
command1
/patern/b end
command2
:end
command3
(3) 命令的两个部分只能执行其中一个:
command1
/pattern/b dothere
command
b
:dothere
command3
t命令的格式和b命令是一样的:
[address]t[label]
它表示的是如果满足address的话,sed脚本就会根据t命令指示的标签进行流程转移。而标签的规则和上面讲的b命令的规则是一样的。下面也给出一个例子:
s/pattern/replacement/
t break
command
:break
对文件进行一次替换:
sed ':a;N;$!ba;s/a/A/g' file
:a 创建一个labela
N 将下一行读入到模式空间
$! 如果不是最后一行,ba跳转到label a处
s/a/A/ 替换a为A,只替换一次
步骤1-3(即:a;N;$!ba;)就是为了将file全部内容读到模式空间中,然后再进行替换,这样替换就只会做一次