sed 高级命令

前面写了一篇文章,关于sed 基础命令的介绍及操作可以查看: sed 基础命令 ;好吧,我们来看看sed 的高级命令,丫的,太多文字了….. 希望你能看明白

sed 和 awk 系列文章:

sed 基础命令:http://www.huangdc.com/109

sed 高级命令:http://www.huangdc.com/123

awk 基础命令 : http://www.huangdc.com/143

awk 高级命令:http://www.huangdc.com/146

高级的sed命令需要更大的决心来掌握,一旦你理解了这些命令,那么就可以认为自己是真正的sed主人了

处理多行模式空间(N、D、P)

采用保持空间来保存模式空间的内容并使用它可用于后续的命令(H、h、G、g、x)

编写使用分支和条件指令的脚本来更改控制流(:、b、t)

高级脚本都做一件共同的事,那就是它们改变了执行或控制的流程顺序。简单的说,就是我们sed 匹配到一行后,可以先做其他的操作(也就是所谓多行模式空间)

通常,一行被读入模式空间并且用脚本的每个命令(一个接着一个的)应用于那 一行。当达到脚本的底部时,输出这一行并且清空模式空间。然后新行被读入模式 空间,并且控制被转移回脚本的顶端。这是sed脚本中正常的控制流。而高级脚本由于各种原因中断或暂停了正常的控制流

高级的sed命令: (先浏览一下)

命令 缩写 功能
Next N 多行Next(N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后来 创建多行模式空间
Delete D 删除模式空间中直到第一个嵌入的换行符的这部分内 容
Print P 输出多行模式空间的第一部分, 直到第一个嵌入的换行符为止
Hold h H 将模式空间的内容复制或追加到保持空间
Get g G 将保持空间的内容复制或追加到模式空间
Exchange x 交换保持空间和模式空间的内容
: : 标签是任意不多于7个字符的序列
Branch b 用于在脚本中将控制转移到另一行
Test t 用于在脚本中将控制转移到另一行

多行模式空间

多行模式空间内容如下:

^The first line\nThe second line$

1、追加下一行(N)

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

也就是说追加一行后,模式空间的内容变成了多行模式:

^The first line\nThe second line$

举个例子:

##  将文本Subscription Services 替换成 Sub Ser ;因为 Subscription Services  分布在文件的2行上,所以需要采用 多行模式空间匹配
DcHuang@linux-fh38:~> cat 1.txt 
My VMware gives you 24/7 access to your Subscription
Services and account details. From one convenient location, 
you can: purchase add-on services, view order history, 
see your service status, receive alerts, and track billing and renewals.

DcHuang@linux-fh38:~> 
DcHuang@linux-fh38:~> sed '/Subscription$/{$!N;s/Subscription\nServices/Sub\nSer/}' 1.txt 
My VMware gives you 24/7 access to your Sub
Ser and account details. From one convenient location, 
you can: purchase add-on services, view order history, 
see your service status, receive alerts, and track billing and renewals.

2、多行删除(D)

删除命令(d) 删除模式空间的内容并导致读入新的输入行,从而在脚本的顶端重新使 用编辑方法

删除命令(D) 稍微有些不同:它删除模式空间中直到第一个嵌入的换行符的这部分内 容。它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用于 模式空间剩余的内容。

也就是说,大写D 多行删除命令将会删除多行模式空间的 红色这部分内容

^The first line\nThe second line$

我们来看看例子 (将多个空行减少到一行); d 和 D 比较,采用D 正确

## 示例文件 1.txt
DcHuang@linux-fh38:~> cat 1.txt 
This line is followed by 1 blank line.

This line is followed by 2 blank line.


This line is followed by 3 blank line.



This line is followed by 4 blank line.




This is the end.

sed_g1

3、多行打印(P)

多行打印(P)命令与小写的p命令稍有不同。该命令输出多行模式空间的第一部分, 直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内 容自动输出(-n选项或#n抑制这个默认的动作)。

也就是说,大写P 多行打印命令将会打印多行模式空间的 红色这部分内容

^The first line\nThe second line$

看个例子:

DcHuang@linux-fh38:~> cat 1.txt 
This line is followed by 1 blank line.
This line is followed by 2 blank line.
This line is followed by 3 blank line.
This line is followed by 4 blank line.
This is the end.

sed_g2

包含那一行(保持空间)

采用保持空间来保存模式空间的内容并使用它可用于后续的命令(H、h、G、g、x)

模式空间是容纳当前输入行的缓冲区。还有一个称为保持空间(hold space)的顶留 (set-aside)缓冲区。模式空间的内容可以复制到保持空间,而且保持空间的内容也 可以复制到模式空间。有一组命令用于在保持空间和模式空间之间移动数据。保持 空间用于临时存储。单独的命令不能寻址保持空间或更改他的内容保持空间的常的 用途是,当改变模式空间中的原始内容是,用于保留当前输入行的副本。影响模式 空间的命令有:(同一命令小写字母和大写字母之间的差别是:小写字母命令改写 目的缓存区的内容,而大写字母命令追加缓存区的现有内容)

命令 缩写 功能
Hold h H 将模式空间的内容复制或追加到保持空间
Get g G 将保持空间的内容复制或追加到模式空间
Exchange x 交换保持空间和模式空间的内容

实例:目的是颠倒以1开始的行和以2开始的行的顺序

[DcHuang@local167 ~]$ cat 1.txt 
111
222
111111
222222
111111111
222222222

sed_g3

流控制命令(:、b、t)

编写使用分支和条件指令的脚本来更改控制流(:、b、t)

分支(b)和测试(t) 命令将脚本中的控制转移到包含特殊标签的行,如何没有指定 标签,则将控制转移到脚本的结尾处。分支命令用于无条件转移,测试命令用于有 条件转移,它们只有当替换命令改变当前行时才会执行

标签是任意不多于7个字符的序列。标签本身占据一行并以冒号开始:

:mylabel

在冒号和标签之间不允许有空格,行结尾处空格将被认为标签的一部分。

当分支命令或者测试命令中指定标签是,在命令和标签之间允许有空格:

b mylabel

1、分支命令(b)

分支命令(b) branch命令用于在脚本中将控制转移到另一行

[address]b[label]

label 是可选的,如果没有给出label,控制就被转到脚本的结尾处。如果有label就 继续执行标签后面的行

[DcHuang@local167 ~]$ cat test.txt 
路人甲 1
路人BB 2
路人CC 3
路人BB 2
路人DD 4

[DcHuang@local167 ~]$ sed '/BB/{:my_label s/DD/Huangdc / ; N;/DD/b my_label}' test.txt 
路人甲 1
路人BB 2
路人CC 3
路人BB 2
路人Huangdc  4

### 1、匹配BB 关键字,然后N 读取下一行,如果匹配 DD ,则返回到 my_label 执行命令
### 2、my_label 接着讲 DD 替换为 Huangdc 
##

2、测试命令(t)

如果在当前匹配地址的行上进行了成功的替换,那么test命令就会转到标签(或者 脚本的结尾)处。test命令语法如下:

[address]t[label]

label 是可选的,如果没有给出label,控制就被转到脚本的结尾处。如果有label就 继续执行标签后面的行

[DcHuang@local167 ~]$ cat test.txt 
路人甲 1
路人BB 2
路人CC 3
路人BB 2
路人CC 4

[DcHuang@local167 ~]$ sed '/3/{ :my_label s/C/K/ ; s/C/d/ ; t my_label ; s/C/T/ }' test.txt
路人甲 1
路人BB 2
路人Kd 3
路人BB 2
路人CC 4

### 匹配包含4 的行,将第一个 D 替换为 K ,第二个 D 替换 d ; 因为包含4的行 没有D,所以测试失败,执行将第一个 C 替换为 T
[DcHuang@local167 ~]$ sed '/4/{ :my_label s/D/K/ ; s/D/d/ ; t my_label ; s/C/T/ }' test.txt
路人甲 1
路人BB 2
路人CC 3
路人BB 2
路人TC 4


### 匹配包含3 的行,将第一个 C 替换为 K ,第二个 C 替换 d ; 因为包含3的行有 D,所以测试失败,执行将第一个 C 替换为 T
[DcHuang@local167 ~]$ sed '/3/{ :my_label s/C/K/ ; s/C/d/ ; t my_label ; s/C/T/ }' test.txt
路人甲 1
路人BB 2
路人Kd 3
路人BB 2
路人CC 4


转载请注明:Huangdc » sed 高级命令

results matching ""

    No results matching ""