当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 8 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-08 14:01 

注册: 2011-04-23 5:28
帖子: 77
地址: 汕尾遮浪
送出感谢: 5
接收感谢: 1
有一个文本如下:
$ cat expl.6
I want to see @fl(what will happen) if we put the
font change commands @fl(on a set of lines). If I understand
things (correctly), the @fl(third) line causes problems. (No?).
Is this really the case, or is it (maybe) just something else?

Let's test having two on a line @fl(here) and @fl(there) as
well as one that begins on one line and ends @fl(somewhere
on another line). What if @fl(it is here) on the line?
Another @fl(one).

现在要作的就是将"[email protected](…)替换为"\fB(…)\fR。以下就是满足条件的sed命令:
$ sed 's/@fl(\([^)]*\))/\\fB\1\\fR/g
> /@fl(.*/{
> N
> s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
> P
> D
> }' expl.6
然而,如果不使用这种输入输出循环,而是单单用N来实现的话,就会出现问题:
$ sed 's/@fl(\([^)]*\))/\\fB\1\\fR/g
> /@fl(.*/{
> N
> s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
> }' expl.6

我运行了两段代码,发现第二段代码的问题出在文本倒数第二行的@fl(it is here)没有被替换。文本前六行都没有触发程序第二行。到第七行时触发程序第二行,于是模式空间追加读入文本第八行,进行程序第四行命令的替换,g选项应该会将两个@fl都替换掉,但最后却没有,why?和第一段代码相比,第二段代码只是删去了P和D,加入P和D两个命令怎么就能全部替换?
百思不得其解,劳驾各位大侠指个路。谢谢!


页首
 用户资料  
 
2 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-08 14:31 

注册: 2010-04-29 22:00
帖子: 61
系统: Gentoo Linux ~amd64
送出感谢: 0 次
接收感谢: 6
第二段代码碰到跨行 @fl 时,要求 s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
而倒数第二行那个没被替换的 @fl() 里面没有 \n


_________________
網站
配置



_________________
评价: 3.7% mafn
 
页首
 用户资料  
 
3 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-08 16:17 
头像

注册: 2005-08-14 21:55
帖子: 58428
地址: 长沙
送出感谢: 4
接收感谢: 274
复杂的sed,以前也搞过。

还是用Perl吧。不蛋疼。


_________________
● 鸣学


页首
 用户资料  
 
4 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-08 17:48 
头像

注册: 2011-11-05 18:53
帖子: 158
地址: 南极圈
送出感谢: 0 次
接收感谢: 7
原来程序的第7行,它是这样执行的:
首先判断你的第一个正则替换,不成立,没有替换成功;
执行N,读入下一行;
执行第二个正则替换,将那个跨行的[email protected]替换了;
执行P,打印从当前模式空间开头到第一个\n的字符,也就是本来的第7行,打印;
执行D,删除从模式空间开头到第一个\n的字符,也就是删掉原来的第7行(包括\n);
循环回到所有命令的开头并且不读入下一行,这时你模式空间的是刚才删掉第7行后剩下的第8行;
第8行又开始执行第一个正则替换。。。如此继续

你的命令里面没有了D,就没有那个删除和循环,当你的程序替换了第7行的那个跨行的[email protected]()以后,没有命令了,这时sed会抹掉当前模式空间的内容并读入下一行(也就是第9行),然后继续新一轮的执行

注意D的作用有两个,有一个是删除模式空间从开头到第一个\n的所有字符,这个好理解
另一个作用是,不要读入新的一行而又从命令的最开头进行执行,这个初学者往往会不清楚



_________________
评价: 3.7% mafn
 
页首
 用户资料  
 
5 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-08 20:58 

注册: 2011-04-23 5:28
帖子: 77
地址: 汕尾遮浪
送出感谢: 5
接收感谢: 1
十分感谢 MaskRay, josephyoung, 两位大侠。
不怕大家见笑,上面这个问题,我上午想了差不多一个小时。呵呵。
首先是自己看走眼了。程序第四行的正则表达式明明不同于第一行的,可是我看了一个小时,竟然没有发现里面的\n!太要命了。
其次对D命令缺乏正确理解。其实不但D,对于N也是,理解不了,往往牵强附会。 josephyoung在四楼的解释非常详细,我想我终于能理解D命令的第二个作用了。
再次感谢两位大侠!


页首
 用户资料  
 
6 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-08 21:31 

注册: 2009-07-01 22:04
帖子: 919
送出感谢: 0 次
接收感谢: 13
sed -n '1h;2,$H; ${g;s/@fl(\([^)]*\))/\\fB\1\\fR/gp}' expl.6
#简化逻辑。
sed '/@fl([^)]*$/N;s/@fl(\([^)]*\))/\\fB\1\\fR/g;P;D' expl.6
#D指令可以这样用。


_________________
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。



_________________
评价: 3.7% mafn
 
页首
 用户资料  
 
7 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-09 0:42 

注册: 2011-04-23 5:28
帖子: 77
地址: 汕尾遮浪
送出感谢: 5
接收感谢: 1
fnan, 我还是喜欢第一句,逻辑简化了,功能也强大多了。
谢谢! :em51


页首
 用户资料  
 
8 楼 
 文章标题 : Re: 遇到一段奇怪的sed代码
帖子发表于 : 2012-01-09 1:03 

注册: 2009-07-01 22:04
帖子: 919
送出感谢: 0 次
接收感谢: 13
sed 'N;s/@fl(\([^)]*\))/\\fB\1\\fR/g;P;D' expl.6
#还可以再简化。


_________________
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 8 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 3 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译