linux匹配文本内容sed,Linux高级文本处理之sed(四)

模式空间是sed内部维护的一个缓存空间,它存放着读入的一行或者多行内容。但是模式空间的一个限制是无法保存模式空间中被处理的行,因此sed又引入了另外一个缓存空间——模式空间(Hold Space)。

一、保持空间

保持空间用于保存模式空间的内容,模式空间的内容可以复制到保持空间,同样地保持空间的内容可以复制回模式空间。sed提供了几组命令用来完成复制的工作,其它命令无法匹配也不能修改模式空间的内容。

操作保持空间的命令如下所示:

444b9f37e491249d.png

这几组命令提供了保存、取回以及交换三个动作,交换命令比较容易理解,保存命令和取回命令都有大写和小写两种形式,这两种形式的区别是小写的是将会覆盖目的空间的内容,而大写的是将内容追加到目的空间,追加的内容和原有的内容是以\n分隔。

二、基本使用

实例1:h命令使用[root@localhost ~]# cat text

1

2

11

22

111

222

[root@localhost ~]# sed 'h' text

1

2

11

22

111

222

实例2:G命令使用[root@localhost ~]# sed 'G' text

1

2

11

22

111

222

[root@localhost ~]#

说明:实例1返回结果正常,因为复制到保持空间的内容并没有取回;实例2每一行的后面都多了一个空行,原因是每行都会从保持空间取回一行,追加(大写的G)到模式空间的内容之后,以\n分隔。

实例3:使用x命令交换空间[root@localhost ~]# sed 'x' text

1

2

11

22

111

a.当读入第一行的时候,模式空间中的内容是第一行的内容,而保持空间是空的,这个时候交换两个空间,导致模式空间为空,保持空间为第一行的内容,因此输出为空行;

b.当读入下一行之后,模式空间为第2行的内容,保持空间为第一行的内容,交换后输出第1行的内容;依次读入每一行,输出上一行的内容;

c.直到最后一行被读入到模式空间,交换后输出倒数第二行的内容,而最后一行的内容并没有输出,此时命令执行结束。

高级命令执行过程图解:

c338b66f8093f8d5.png

sedsed调试过程:[root@localhost ~]# sedsed -d 'H;g' num

PATT:a$

HOLD:$

COMM:H

PATT:a$

HOLD:\na$

COMM:g

PATT:\na$

HOLD:\na$

a

PATT:b$

HOLD:\na$

COMM:H

PATT:b$

HOLD:\na\nb$

COMM:g

PATT:\na\nb$

HOLD:\na\nb$

a

b

PATT:c$

HOLD:\na\nb$

COMM:H

PATT:c$

HOLD:\na\nb\nc$

COMM:g

PATT:\na\nb\nc$

HOLD:\na\nb\nc$

a

b

c

三、流程控制命令

为了使使用者在书写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

实例1:将把empnametitle.txt文件中的雇员名称和职位合并到一行内,字段之间以分号:

分隔,并且在管理者的名称前面加上一个星号*。[root@localhost ~]# cat emp.txt

John Doe

CEO

Jason Smith

IT Manager

Raj Reddy

Sysadmin

Anand Ram

Developer

Jane Miller

Sales Manager

[root@localhost ~]# cat label.sed

N

s/\n/:/

/Manager/!b end

s/^/*/

:end

p

[root@localhost ~]# sed -nf label.sed emp.txt

John Doe:CEO

*Jason Smith:IT Manager

Raj Reddy:Sysadmin

Anand Ram:Developer

*Jane Miller:Sales Manager

t命令的格式和b命令是一样的:[address]t[label]

它表示的是如果满足address的话,sed脚本就会根据t命令指示的标签进行流程转移。命令t的作用是,如果前面的命令执行成功,那么就跳转到t指定的标签处,继续往下执行

后续命令。 否则,仍然继续正常的执行流程。 下面也给出一个例子:s/pattern/replacement/

t break

command

:break

实例2:将把empnametitle.txt文件中的雇员名称和职位合并到一行内,字段之间以分号:

分隔,并且在管理者的名称前面加上三个星号*[root@localhost ~]# cat emp.txt

John Doe

CEO

Jason Smith

IT Manager

Raj Reddy

Sysadmin

Anand Ram

Developer

Jane Miller

Sales Manager

[root@localhost ~]# cat t.label

h;n;H;x    #此处等同于N命令的作用效果

s/\n/:/

:repeat

/Manager/s/^/*/

/\*\*\*/!t repeat

p

[root@localhost ~]# sed -nf t.label emp.txt

John Doe:CEO

***Jason Smith:IT Manager

Raj Reddy:Sysadmin

Anand Ram:Developer

***Jane Miller:Sales Manager

注意:分支命令b用于无条件转移,测试命令t用于有条件转移,他们只有当替换命令改变当前行时才会执行。

四、sed实战

实例1:使用sed模拟出tac的功能(倒序输出)[root@localhost ~]# cat num

1

2

3

4

5

[root@localhost ~]# sed '1!G;h;$!d' num

5

4

3

2

1

实例2:行列转换[root@localhost ~]# cat num

1

2

3

4

5

[root@localhost ~]# sed -ne 'H;${x;s/\n/ /g;p}' num

1 2 3 4 5

实例3:行列转换100之内数字求和[root@localhost ~]# seq 100|sed -ne 'H;${x;s/\n/+/g;s/^+//p}'|bc

5050

实例4:追加匹配行到行尾[root@localhost ~]# cat file

0

1 hello

2

3 hello

4

5

[root@localhost ~]# sed -e '/hello/{H;d}' -e '$G' file

0

2

4

5

1 hello

3 hello

实例5:在文件中每行后面加空白行[root@localhost ~]# cat num

1

2

3

4

5

[root@localhost ~]# sed 'G' num

1

2

3

4

5

[root@localhost ~]#

实例6:保留文件最后一行[root@localhost ~]# sed '$!d' num

5

实例7:保留文件的每一行后方有且只有一个空白行[root@bash ~]# cat /etc/issue

\S

Kernel \r on an \m

Geek Young Learning Services

http://www.geekyoung.com

[root@bash ~]# sed '/^$/d;G' /etc/issue

\S

Kernel \r on an \m

Geek Young Learning Services

http://www.geekyoung.com

实例8:保留奇数行[root@localhost ~]# cat num

1

2

3

4

5

[root@localhost ~]# sed 'n;d' num

1

3

5

实例9:去基名[root@localhost ~]# echo '/etc/sysconfig/network-scripts'|sed -r 's@^.*/([^/]+)/?$@\1@'

network-scripts

实例10:取目录名[root@localhost ~]# echo '/etc/sysconfig/network-scripts/'|sed -r 's@[^/]+/?$@@'

/etc/sysconfig/

实例11:引用系统变量[root@localhost ~]# a=2

[root@localhost ~]# cat num

a

b

c

[root@localhost ~]# sed -n ''$a',3p' num

b

c

总结:sed高级用法灵活多变,使用前要搞清楚模式空间的内容,以及sed命令的执行过程,到此sed用法就结束了,要想灵活使用sed还得多练。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值