浅析sed循环与N操作

        之前执行删除回车符都使用tr或者vi,突然想到怎么用sed删除回车符:

# cat test

1111111111

222222222

333333333

444444444

         想当然的执行:

#sed 's/\n/\t/' test

1111111111

222222222

333333333

444444444

        没有成功!

        原因是sed读入一行,会去掉尾部换行符(但会保留$),存入pattern space,然后执行编辑命令,也可以顺序执行多个操作,中间用";"隔开,如:

#sed 's/1/x/1;s/1/b/2' test

x1b111111

222222222

333333333

444444444

        第二个s操作,由于第1个1被第一个s操作替换成了x,第2个1变成了第1个1。


        处理完毕,除非加了-n参数,把当前的pattern space打印出来,否则会在后边重新添加去掉的换行符,然后把pattern space内容给hold space,把pattern space清空。

        在网上搜索了下,sed删除回车符的命令为:sed ':a;N;$!ba;s/\n/ /g' test

        开始并不懂这条命令什么意思,之前也很少用,通过试验,终于有所了解,总结一下:

# sed ':loop;N;$!bloop;s/\n/\t/g' test

111111111   222222222       333333333       444444444      

         :loop(该循环名称可以自定义比如:a):表示sed进入循环,逐行将文本读入Pattern Space

          N  :这里就是循环里面所做的操作(当然我们也可以进行其他操作)N表示将文本的下一行追加到Pattern space,产生一个新行。

         (在使用N的时候两行之间的$会取消)

          $!bloop :循环结束标志,sed遇到最后行将退出循环否则返回loop

         然后执行替换操作,s将回车(\n)替换成制表符(\t)


         Pattern Space中的内容与执行的过程如下:

读取内容        是否为最后一行           Pattern Space

111111111            否                  ^111111111$

222222222            否                  ^11111111\n222222222$

333333333            否                  ^111111111\n222222222\n333333333$

44444444             是                  ^111111111\n222222222\n333333333\n44444444$

退出循环后, 执行s操作将\n替换成\t则为:^111111111\t222222222\t333333333\t44444444$

这是时候“\n”在pattern space中匹配序号在是依次排序为(1,2,3)

分别执行

#sed ':loop;N;$!bloop;s/\n/\t/1' test

111111111       222222222

333333333

444444444

# sed ':loop;N;$!bloop;s/\n/\t/2' test

111111111

222222222       333333333

444444444

# sed ':loop;N;$!bloop;s/\n/\t/3' test

111111111

222222222

333333333       444444444

了解pattern space里面的内容,就方便多了。执行:

sed ':loop;N;$!bloop;s/$/x/g' test

执行s操作将$替换成x则为:^111111111\n222222222\n333333333\n44444444x即:

111111111

222222222

333333333

444444444x

再看看,不对N进行循环操作,依次执行N;s操作

[root@dgtest ~]#sed 'N;s/\n/\t/' test

Pattern Space中的内容与执行的过程如下:

读入内容                          Pattern Space

1111111111                         ^1111111111$

222222222                          ^1111111111\n222222222$

执行s操作将\n替换成\t则为:  111111111\t222222222$,清空!

333333333                          ^33333333$

44444444                           ^33333333\n44444444$

执行s操作将\n替换成\t则为:  ^33333333\t44444444$

显然这个命令的输出结果为:

111111111       222222222

333333333       444444444

         将test新增一行555555555

#sed 'N;s/^/x/' test

x111111111

222222222

x333333333

444444444

555555555

         读取最后一行555555555的时候,不能再读一下行,退出了操作,没有在行首添加x

         再比较下$!N与N的区别

# sed '$!N;s/^/x/' test

x111111111

222222222

x333333333

444444444

x555555555
        $!N在执行N没有成功的时候,不会马上退出sed,而会去执行后续的操作,这里是在行首添加x


         在vi中我们可以使用%s/\(^.*$\)\n\(^.*$\)/\1/删除偶数行,%s/\(^.*$\)\n\(^.*$\)/\2/删除奇数行

         通过上面实验,我们也可以使用sed实现同样的操作。

# sed -n 'N;s/\(^.*\)\n\(.*$\)/\1/g;p' test

111111111

333333333

# sed -n 'N;s/\(^.*\)\n\(.*$\)/\2/g;p' test

222222222

444444444

        但是如果是奇数行的话,最后一行将不显示,原因就是最后一行不能读取下一行,就退出了sed,没执行变更操作。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值