contents
- 多行命令
- next 命令
- 单行的next命令
- 合并文本行
- 多行删除命令
- 多行打印命令
- 保持空间
- 排除命令
- 改变流
- 分支
- 测试
- 模式替换
- &符号
- 替代单独的单词
- 在脚本中使用 sed
- 使用包装脚本
- 重定向 sed 的输出
- 创建 sed 实用工具
- 加倍行间距
- 对可能含有空白行的文件加倍行间距
- 给文件中的行编号
- 打印末尾行
- 删除行
- 删除HTML标签
多行命令
在sed编辑器读取数据流时,它会基于换行符的位置将数据分成行。sed编辑器根据定义好的脚本命令一次处理一行数据,然后移到下一行重复这个过程。
如果你在文本数据中查找某个短语时,他有可能被分隔成跨行显示,如果用普通的sed编辑器命令来处理文本,就不可能发现这种被分开的短语。
sed编辑器包含了三个可用来处理多行文本的特殊命令:
- N:将数据流中的下一行加进来创建一个多行组来处理。
- D:删除多行组中的一行。
- P:打印多行组中的一行。
next 命令
单行的next命令
通常sed编辑器在移动到数据流中的下一行文本前,会在当前行上执行完所有定义好的命名。而next命令,会告诉sed编辑器移动到数据流中的下一行文本,而不是重新执行命令。
sed '/header/{n ; d}' data.txt
脚本查找含有单词header的那一行,找到后,n命令会让sed编辑器移动到文本的下一行,sed编辑器会继续执行命令列表,该命令列表使用d命令来删除空白行,sed编辑器执行完命令脚本后,会从数据流中读取下一行文本,并从头开始执行命令脚本。
合并文本行
单行next命令会将数据流中的下一文本行移动到sed编辑器的工作空间。多行版本的next命令(N)会将下一文本行添加到模式空间中已有的文本后。
这样的作用是将数据流中的两个文本行合并到统一模式空间中。文本行仍然用换行符分隔,但sed编辑器现在会将两行文本当成一行来处理。
sed '/first/{ N ; s/\n/ / }' data.txt
sed 编辑器脚本查找含有单词first的那行文本,找到该行后,它会用N命令将下一行合并到那行,然后用替换命令s将换行符替换成空格。
多行删除命令
和N命令一起使用时,使用单行删除命令就要小心了。
sed 'N ; /System\nAdministrator/d' data.txt
删除命令会在不同行中查找单词System和Administrator,然后再模式空间中将两行都删掉。这未必是你想要的结果。
sed编辑器提供了多行删除命令D,它只删除模式空间中的第一行,该命令会删除到换行符(含换行符)为止的所有字符。
sed 'N ; /System\nAdministrator/D' data.txt
sed '/^$/{N ; /header/D}' data.txt
sed 编辑器脚本会查找空白行,然后用N命令来将下一文本行添加到模式空间。如果新的模式空间内容含有单词header,则D命令会删除模式空间中的第一行。如果不结合使用N命令和D命令,就不能再不删除其他空白行的情况下只删除第一个空白行。
多行打印命令
现在,你可能已经了解了单行和多行版本命令的差异,多行打印命令(P)沿用了同样的方法。它只打印多行模式空间中的第一行。这包括模式空间中直到换行符为止的所有字符。
D命令的独特之处在于强制sed编辑器返回到脚本的起始处,对同一模式空间中的内容重新执行这些命令。在命令脚本中加入N命令,你就能单步扫过整个模式空间,将多行一起匹配。
使用P命令打印出第一行,然后用D命令删除第一行并绕回到脚本的起始处。一旦返回,N命令会读取下一行文本并重新开始这个过程。这个循环会一直继续下去,直到数据流结束。
保持空间
模式空间是一块活跃的缓冲区,在sed编辑器执行命令时它会保存待检查的文本。但它并不是sed编辑器保存文本的唯一空间。
sed编辑器有另一块称作保持空间的缓冲区域,在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。
保持空间命令:
命令 | 描述 |
h | 将模式空间复制到保持空间 |
H | 将模式空间附加到保持空间 |
g | 将保持空间复制到模式空间 |
G | 将保持空间附加到模式空间 |
x | 交换模式空间和保持空间的内容 |
通常,在使用h或H命令将字符串移动到保持空间后,最终还要用g、G或x命令将保存的字符串移回模式空间。
(未完待续…)
排除命令
你可以配置命令使其不要作用到数据流中的特定地址或地址空间。
感叹号命令用来排除命令,让原本会起作用的命令不起作用。
sed -n '/header/!p' data.txt
除了包含单词header那一行外,文件中其他所有的行都被打印出来了。
(未完待续…)
改变流
通常sed编辑器会从脚本的顶部开始,一直执行到脚本的结尾(D命令是个例外,它会强制sed编辑器返回到脚本的顶部,而不读取新的行)
分支
sed 编辑器提供了一种方法,可以基于地址、地址模式或地址区间排除一整块命令。
[addres]b [label]
address 参数决定了哪些行的数据会触发分支命令。label 参数定义了要跳转到的位置,如果没有加入label参数,跳转命令会跳到脚本的结尾。
sed '{2,3b; s/This is/Is this/ ; s/line./test?/}' data.txt
分支命令在数据流中的第2行和第3行处跳过了两个替换命令。
要是不想直接跳到脚本的结尾,可以为分支命令定义一个要跳转的标签,标签以冒号开始,最多可以是7个字符长度。
(未完待续…)
测试
测试命令(t)也可以用来改变sed编辑器脚本的执行流程,测试命令会根据替换命令的结果跳转到某个标签,而不是根据地址进行跳转。
[address]t [label]
跟分支命令一样,在没有指定标签的清空下,如果测试成功,sed会跳转到脚本的结尾。如果已经做了一个替换,不需要再做另一个替换,那么测试命令能帮上忙。
sed '{
s/first/matched/
t
s/This is the/No match on/
}' data.txt
第一个替换命令会查找模式文本first,如果匹配了行中的模式,它就会替换文本,而且测试命令会跳过后面的替换命令,如果第一个替换命令未能匹配模式,第二个替换命令就会被执行。
当无需替换时,测试命令不会跳转而是继续执行剩下的脚本。
模式替换
如果你只是要匹配模式中的一个单词:
$ echo "The cat sleeps in his hat." | sed 's/cat/"cat"/'
The "cat" sleeps in his hat.
但是如果你在模式中用通配符来匹配多个单词呢?
$ echo "The cat sleeps in his hat." | sed 's/.at/"".at"/g'
The ".at" sleeps in his ".at".
用于替代的字符串无法匹配已匹配单词中的通配符字符。
&符号
&符号可以用来代替命令中匹配的模式。不管模式匹配的是什么样的文本,你都可以在替代模式中使用&符号来使用这段文本。
$ echo "The cat sleeps in his hat." | sed 's/.at/"&"/g'
The "cat" sleeps in his "hat".
当模式匹配到了单词cat,"cat"就会出现在了替换后的单词里。当它匹配了单词hat,"hat"就出现在了替换后的单词中。
替代单独的单词
在脚本中使用 sed
使用包装脚本
重定向 sed 的输出
创建 sed 实用工具
加倍行间距
对可能含有空白行的文件加倍行间距
给文件中的行编号
打印末尾行
删除行
删除HTML标签