首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >awk与sed:关于多行的样本

awk与sed:关于多行的样本

作者头像
全栈程序员站长
发布2022-07-05 19:41:56
发布2022-07-05 19:41:56
9170
举报

大家好,又见面了,我是全栈君

几天前CSDN看到一个帖子 http://bbs.csdn.net/topics/390848841 ,楼主贴了以下的问题:

代码语言:javascript
复制
     例:
     
     12345
     
     67890
     
     1234567890
     
     123
     
     4567890
     
     怎样能把上面数据转换成
     
     1234567890
     
     1234567890
     
     1234567890

看了几位网友的回复。认为还是挺有意思,也收获了一些知识,由于部分网友仅仅给出了解决方法,没有解释下。我依据自己的理解,对几个答案解释下(不一定准确,错误之处请指正)

我觉得错的答案

1 首先楼主给出了一个他说调试不出来的答案:

代码语言:javascript
复制
     sed 's/(?!90)\n//g'

?!

应该是非pattern结尾的意思,这个答案应该是说把非90结尾的行的换行符换位空。

这个答案应该是不可行的。sed默认单行模式。一次处理一行,执行时发现,就算我们把换行符去掉了。sed命令结束后。还是将它当成完整的一行输出(也就是说,应该是自己主动又加上换行符了)

2. 有一位网友。认为其它答案太复杂,给出了以下的方法

代码语言:javascript
复制
sed ‘N;s/\n//g’

这个答案使用了sed的多行模式,但应该是无法实现楼主的目的的。我们看执行结果“

代码语言:javascript
复制
windeal@ubuntu:~/Windeal/shell$ sed 'N;s/\n//g' a.txt 123456789012345678901234567890

能够看出,sed 的N命令把第二行接到第一行后面,把第四行接到第三行后面,没有考虑到我们目标中:仅仅有非90结尾的才把下一行附加上来。所以第四行的123被附加到第三行1234567890而出现了错误的结果。

我觉得对的答案

再来看两个我觉得对的答案:

1.

代码语言:javascript
复制
sed -e '/^/{:loop /90$/!{N;b loop};s/\n//g}' test.txt > t2.txt
改一下好理解一点就是
sed '{:myloop /90$/!{N;b myloop};s/\n//g}' a.txt

/^/的意思我没弄明确。应该是匹配每一行吧

在该命令中。myloop是一个自己定义的标签。

类似程序语言中goto用的标签。 N表示多行模式,b表示分支(相当于goto)

这样就好理解了。sed会读取一行内容,假设这一行不是以90结尾。/90$/! 就为真,进入 {N;b myloop}。

N就进入了多行模式。把下一行附加上来,然后进入分支b myloop,在推断是不是以90结尾,这样重复读取,直到读到以90结尾的行。

接下来模式空间的读取工作已经完毕。进入下一个命令。替换。s/\n//g​这个命令把当前模式空间的换行符都转换为空,也就是拼接成一行。

如此,我们就完毕了我们要的目的。

2.

代码语言:javascript
复制
awk '{if($0~/90$/){print}else{printf("%s",$0)}}' a.txt 

这个答案读取了一行的所以字段(实际上就1个字段,) 用$0表示,然后 if($0~/90$/)推断是不是以90结尾。

假设以90结尾,就输出当前行数据。

假设不是,就格式化输入当前航的字符串

注意print和printf的差别

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/117721.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档