Appearance
sed
进阶
未必会用到但是最好理解
多行命令
sed
处理的时候只对一行进行处理, 有些短语会被分割为多行
三个用来处理多行文本的特殊命令
- N: 将数据流中的下一行加进来创建一个多行组(multiline group)来处理。
- D:删除多行组中的一行。
- P:打印多行组中的一行。
next命令
单行的next命令
小写的n会告诉sed
编辑器移动到数据流中的下一文本行,而不用重新回到命令的最开始再执行一遍
sed
编辑器在移动到数据流中的下一文本行之前,会在当前行上执行完所有定义好的命令。单行next命令改变了这个流程
**个人理解:**对数据进行查找, 找到之后对下一行进行处理
bash
$ cat data1.txt
This is the header line.
This is a data line.
This is the last line.
$ sed '/header/{n ; d}' data1.txt
This is the header line.
This is a data line.
This is the last line.
合并文本行
单行next命令会将数据流中的下一文本行移动到sed
编辑器的工作空间(称为模式空间)。多行版本的next命令(用大写N)会将下一文本行添加到模式空间中已有的文本后。
**注: **每两行为一组, 不进行重复的测试
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed 'N; s/3\n/ /' data1.txt
Line 1
Line 2
Line Line 4
Line 5
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed 'N; s/4\n/ /' data1.txt
Line 1
Line 2
Line 3
Line 4
Line 5
文本行仍然用换行符分隔,但sed
编辑器现在会将两行文本当成一行来处理
bash
sed '/first/{ N ; s/\n/ / }' data2.txt
This is the header line.
This is the first data line. This is the second data line.
This is the last line.
合并两行
如果要在数据文件中查找一个可能会分散在两行中的文本短语的话,这是个很实用的应用程序。这里有个例子
bash
$ cat data3.txt
On Tuesday, the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.
Thank you for your attendance.
sed 'N ; s/System.Administrator/Desktop User/' data3.txt # 使用.代表空格或者换行符
On Tuesday, the Linux Desktop User's group meeting will be held.
All Desktop Users should attend.
Thank you for your attendance.
如果是换行符, 会把他替换为空格, 导致两行合并为一行
可以使用多种替换方式
bash
$ sed 'N
> s/System\nAdministrator/Desktop\nUser/
> s/System Administrator/Desktop User/
> ' data3.txt
这个脚本总是在执行sed
编辑器命令前将下一行文本读入到模式空间。当它到了最后一行文本时,就没有下一行可读了,所以N命令会叫sed
编辑器停止。如果要匹配的文本正好在数据流的最后一行上,命令就不会发现要匹配的数据
可以把处理单行的格式放在N前面
bash
$ sed '
> s/System Administrator/Desktop User/
> N
> s/System\nAdministrator/Desktop\nUser/
> ' data4.txt
多行删除命令
单行删除命令(d)。sed
编辑器用它来删除模式空间中的当前行。但和N命令一起使用时,使用单行删除命令就要小心了
会把两行全部删除, 如果只想删除第一行, 应该使用D命令, 只删除到换行符
可以用来结合删除特定位置的空白行
多行打印命令
P命令, 只打印第一行的内容
保持空间
模式空间是一块活跃的缓冲区, sed
编辑器会检查他保存的文本
有另一块称作保持空间(hold space)的缓冲区域。在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。
有5条命令可用来操作保持空间
命令 | 描述 |
---|---|
h | 将模式空间复制到保持空间 |
H | 将模式空间附加到保持空间 |
g | 将保持空间复制到模式空间 |
G | 将保持空间附加到模式空间 |
x | 交换模式空间和保持空间的内容 |
可以用来反向输出两行
bash
$ sed -n '/first/ {h ; n ; p ; g ; p }' data2.txt
This is the second data line.
This is the first data line.
排除命令
可以使用命令来通过地址排除某些行
使用( ! )来排除某些行时候调用的命令
在处理N命令的时候不能识别最后一行, 可以使用排除命令
bash
$ sed '$!N;
> s/System\nAdministrator/Desktop\nUser/
> s/System Administrator/Desktop User/
> ' data4.txt
可用来反转一段对话的输出顺序
把每一行的先放入保持空间, 然后在下一行的时候把他放到模式空间后面, 在最后一行的时候进行打印
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed -n '1!G; h ; $p' data1.txt
Line 5
Line 4
Line 3
Line 2
Line 1
tac命令会倒序显示一个文本文件。你也许已经注意到了,这个命令的名字很巧妙,它执行的正好是与cat命令相反的功能。
改变流
通常,sed
编辑器会从脚本的顶部开始,一直执行到脚本的结尾(D命令是个例外,它会强制sed编辑器返回到脚本的顶部,而不读取新的行)
分支
sed
编辑器提供了一种方法,可以基于地址、地址模式或地址区间排除一整块命令。
使用命令b
bash
[address]b [label]
address参数决定了哪些行的数据会触发分支命令。label参数定义了要跳转到的位置。如果没有加label参数,跳转命令会跳转到脚本的结尾
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed '2,3b ; s/Line/line/; s/[15]/?/' data1.txt
line ?
Line 2
Line 3
line 4
line ?
不对2,3行进行处理
要是不想直接跳到脚本的结尾,可以为分支命令定义一个要跳转到的标签。标签以冒号开始,最多可以是7个字符长度
bash
: label
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed '2,3b jump; s/Line/line/;: jump; s/[135]/?/' data1.txt
line ?
Line 2
Line ?
line 4
line ?
可以向前跳跳转形成循环
bash
$ echo "This, is, a, test, to, remove, commas." | sed -n '{
> :start
> s/,//1p
> /,/b start # 加一个条件防止形成死循环
> }'
测试
t命令, 测试命令会根据替换命令的结果跳转到某个标签,而不是根据地址进行跳转
替换命令成功匹配并替换了一个模式,测试命令就会跳转到指定的标签。如果替换命令未能匹配指定的模式,测试命令就不会跳转
bash
[address]t [label]
跟分支命令一样,在没有指定标签的情况下,如果测试成功,sed
会跳转到脚本的结尾
bash
$ echo "This, is, a, test, to, remove, commas. " | sed -n '{
> :start
> s/,//1p
> t start # 只有在上面替换成功的时候进行循环, 去除所有的','
> }'
模式替代
在使用通配符的时候很难知道什么文本会被匹配
&符号
sed
编辑器提供了一个解决办法。&符号可以用来代表替换命令中的匹配的模式。不管模式匹配的是什么样的文本,你都可以在替代模式中使用&符号来使用这段文本。
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ echo "The cat set in its hat" | sed 's/.at/"&"/g'
The "cat" set in its "hat"
替代单独的单词
有时候你只想使用一部分
sed
编辑器用圆括号来定义替换模式中的子模式。你可以在替代模式中使用特殊字符来引用每个子模式。替代字符由反斜线和数字组成。数字表明子模式的位置。sed
编辑器会给第一个子模式分配字符\1,给第二个子模式分配字符\2,依此类推
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ echo "This is a test text" | sed 's/a \(test\)/\1/'
This is test text
用来处理替换的对象有一部分为原数据
- 用来在大串的数字中插入逗号
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ echo "123456789" | sed '{:start; s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/; t start}' # 匹配的字符串是最起码有四个数字, 把后面的三个数字分为一组
123,456,789
在脚本中使用sed
使用包装脚本
实现sed
脚本的过程十分繁琐, 尤其是脚本很长的话, 可以把脚本放到包装脚本中
包装脚本充当着sed
编辑器脚本和命令行之间的中间人角色
bash
1 #!/bin/bash
2
3 sed -n '{ 1!G; h ; $p }' $1
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ test2.sh data1.txt
Line 5
Line 4
Line 3
Line 2
Line 1
重定向sed
输出
正常情况下会出出到STDOUT上
创建实用工具
加倍行间距
加倍行间距
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed 'G' data1.txt
Line 1
Line 2
Line 3
Line 4
Line 5
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$
可以使用
!$G
不添加最后一行
对可能已经存在空行的文件加倍行距
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed '/^$/d ;$!G' data1.txt
Line 1
Line 2
Line 3
Line 4
Line 5
给文件的行标号
使用等号进行编号有些难看
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed '=' data1.txt | sed 'N; s/\n/ /'
1 Line 1
2 Line 2
3 Line 3
4 Line 4
5 Line 5
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ nl data1.txt
1 Line 1
2 Line 2
3 Line 3
4 Line 4
5 Line 5
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ cat -n data1.txt
1 Line 1
2 Line 2
3 Line 3
4 Line 4
5 Line 5
其他的方式有可能会增加额外的参数
打印末尾行
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed -n '$p' data1.txt
Line 5
显示后几行
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed '{
:start
$q; N; 3,$D # 退出循环; 再插新的入一行 ; 如果已经读取的大于第三行, 删除最上面(只留下两行)
b start
}' data1.txt
Line 4
Line 5
删除行
删除连续的空白行
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/20$ sed '/./,/^$/!d' data1.txt
Line 1
Line 2
Line 3
Line 4
Line 5
在匹配时候会匹配到有空行以及一个和它相连的行, 不会进行删除, 其他的都删除了, 没有空行的时候会一直进行匹配
删除文件开头的行
bash
/./,$!d
删除结尾
bash
sed '{
:start
/^\n*$/{$d; N ; b start}
}'
会匹配只有一个换行的行, 检查是不是最后一行, 是的话删除最后一行, 不是的话会添加新的一行, 进行循环
删除html标签
bash
s/<.*>//g
会删除一行中离得最远的大于小于号之间的
bash
s/<[^>]*>//g
删除两个中间没有大于号的尖括号之间的所有东西
会导致出现空行
bash
sed 's/<[^>]*>//g ; /^$/d' data11.txt