免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6978 | 回复: 13
打印 上一主题 下一主题

[文本处理] sed中模式加行号匹配问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-08-05 11:03 |只看该作者 |倒序浏览
dat文档内容如下:
  1. xian@QA:~$ cat dat
  2. 1 dat                                                     #6是address,p是function,下同
  3. 2 Desktop
  4. 3 dir1
  5. 4 dir2
  6. 5 Documents
  7. 6 Music                                                 #sed默认是自动输出的
  8. 6 Music                                                 #这一行是由命令p输出的
  9. 7 Pictures
  10. 8 Public
  11. 9 Templates
  12. 10 Videos
复制代码
以dat文档做测试:
  1. xian@QA:~$ sed -n '0,/Public/{s//private/p}' dat
  2. 8 private
复制代码
1.0代表什么意思呢?行号不是从1开始的吗?
  1. xian@QA:~$ sed -n '1,/D/{s//private/p}' dat
  2. sed: -e expression #1, char 0: no previous regular expression
复制代码
2.从行号1开始时,为什么s替换内容不能省略呢?
  1. xian@QA:~$ sed -n '1,/D/{s/D/private/p}' dat
  2. 2 privateesktop
复制代码
3.这个例子中的1,/D/是指从第一行到第一个匹配到字符D吗?

请各位老大们指点一下。。。

论坛徽章:
33
ChinaUnix元老
日期:2015-02-02 08:55:39CU十四周年纪念徽章
日期:2019-08-20 08:30:3720周年集字徽章-周	
日期:2020-10-28 14:13:3020周年集字徽章-20	
日期:2020-10-28 14:04:3019周年集字徽章-CU
日期:2019-09-08 23:26:2519周年集字徽章-19
日期:2019-08-27 13:31:262016科比退役纪念章
日期:2022-04-24 14:33:24
2 [报告]
发表于 2014-08-05 11:52 |只看该作者
用0开始比较安全,你体会一下这个数据:
1 Public
2 Desktop
3 dir1
4 dir2
5 Documents
6 Music
7 Pictures
  1. sed -n '0,/Public/p' dat
复制代码
  1. sed -n '1,/Public/p' dat
复制代码

论坛徽章:
1
处女座
日期:2014-09-18 16:18:00
3 [报告]
发表于 2014-08-05 12:17 |只看该作者
回复 1# siyecaoliu
不知道为什么1开始不能省略,但是用你的代码做了测试,发现如果第一行有满足匹配的内容,那么用1的话会多匹配一行,但是用0不会
  1. [kasio@localhost shell]$ sed -n '1,/Desktop/{s/Desktop/***/p}' testfile
  2. 1 ***
  3. 2 ***
  4. [kasio@localhost shell]$ sed -n '0,/Desktop/{s/Desktop/***/p}' testfile
  5. 1 ***
  6. [kasio@localhost shell]$
复制代码
testfile:
  1.   1 1 Desktop
  2.   2 2 Desktop
  3.   3 3 dir1
  4.   4 4 dir2
  5.   5 5 Documents
  6.   6 6 Music
  7.   7 7 Pictures
  8.   8 8 Desktop
  9.   9 9 test
  10. 10 10 Desktop
  11. ~                        
复制代码

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
4 [报告]
发表于 2014-08-05 13:26 |只看该作者
回复 1# siyecaoliu


    1.参见sed的manual
0,/regexp/
    A line number of 0 can be used in an address specification like 0,/regexp/ so that sed will try to match regexp in the first input line too. In other words, 0,/regexp/ is similar to 1,/regexp/, except that if addr2 matches the very first line of input the 0,/regexp/ form will consider it to end the range, whereas the 1,/regexp/ form will match the beginning of its range and hence make the range span up to the second occurrence of the regular expression.

    Note that this is the only place where the 0 address makes sense; there is no 0-th line and commands which are given the 0 address in any other way will give an error.

2.因为你用的是add,/regex/的形式,那么在替换时没有搜索内容的。如果用的是/regex/,/regex2/或者/regex/那么是可以的。

3. 1,/D/是从第一行到第一个含有D的那一行。 注意跟/regex/,/regex2/区分,如果这儿用的是/d/,/D/那么后面的/D/表示匹配到最后一个包含D的那一行。

论坛徽章:
0
5 [报告]
发表于 2014-08-05 14:20 |只看该作者
谢谢HAT大神, 试了一下
  1. xian@QA:~$ sed -n '0,/Public/p' dat
  2. 1 Public
  3. xian@QA:~$ sed -n '1,/Public/p' dat
  4. 1 Public
  5. 2 Desktop
  6. 3 dir1
  7. 4 dir2
  8. 5 Documents
  9. 6 Music
  10. 7 Pictures
复制代码
引用四楼的一段话
if addr2 matches the very first line of input the 0,/regexp/ form will consider it to end the range, whereas the 1,/regexp/ form will match the beginning of its range and hence make the range span up to the second occurrence of the regular expression.
我理解的是当第一行有匹配项的时候,0,/regexp/ 会在匹配完第一行之后,不在进行匹配,所以这里输出的是第一行的数据;而1,/regexp/会在第一行匹配完成后,从第二行开始匹配第二次出现该字符串的行,而在上面的例子中没有匹配项,所以会一直查找到文档结尾,不知道我这样理解,对不对呢?
回复 3# Shell_HAT


   

论坛徽章:
0
6 [报告]
发表于 2014-08-05 14:28 |只看该作者
嗯嗯,这个还是HAT大神说的安全性的问题,如果第一行匹配的话,0,/regexp/ 只匹配一次,而1,/regexp/会进行第二次匹配,可以看下5楼的解答,应该会更清楚些~
回复 4# Kasiotao


   

论坛徽章:
0
7 [报告]
发表于 2014-08-05 15:44 |只看该作者
先谢谢大神的解答~
问题1没有疑问了,
问题2,这里0,/regex/在替换时是可以省略替换的内容的,这个是为什么呢?另外我测试了/regex1/,/regex2/的情况
  1. xian@QA:~$ vi dat

  2. 1 dat                                                     #6是address,p是function,下同
  3. 2 Desktop
  4. 3 dir1
  5. 4 dir2
  6. 5 Documents
  7. 6 Music                                                 #sed默认是自动输出的
  8. 6 Music                                                 #这一行是由命令p输出的
  9. 7 Pictures
  10. 8 Public
  11. 9 Templates
  12. 10 Videos
  13. xian@QA:~$ sed -n '/dat/,/Music/{s//replaced/p} ' dat
  14. 1 replaced                                                     #6是address,p是function,下同
  15. 6 replaced
复制代码
在这种情况下,/regex1/,/regex2/两个字符串都会被替代,
问题3,/regex1/,/regex2/的情况下,/regex2/匹配的也是第一个含有/regex2/的那一行,测试结果在上问题2中
回复 5# 欧阳西风


   

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
8 [报告]
发表于 2014-08-05 16:24 |只看该作者
本帖最后由 欧阳西风 于 2014-08-05 16:25 编辑

回复 8# siyecaoliu


    果然看的够仔细,我之前也没有好好考虑这个问题。特意又去试了一下。

/regex1/,/regex2/这样的 确实是匹配到第一个/regex2/出现的那一行,可能是我之前的测试条件有点儿问题。

0,/regex/之后s命令可以不用输入查找内容,我之前的解释可能稍微有点儿问题,在此更正一下。
按照我的理解,只要addr,/regex/当中的/regex/做过一次判断,也就有了匹配内容,那么后面就不用再输入了,如果没有的话,那么就会报错。

那么刚刚的那个问题就比较容易解释了,如果使用addr,/regex/,当addr大于0时,由于addr行根本就没有判断/regex/,仅仅判断了addr.所以后面的匹配内容是空,就会报错。
回来再看addr是0 的情况,0,/regex/ 按照manual的解释:
A line number of 0 can be used in an address specification like 0,/regexp/ so that sed will try to match regexp in the first input line too.

也就是说使用0,/regex/的情况下,从第一行开始每一行都会做/regex/判断,所以后面的匹配内容不为空,就会正常执行了。


PS: 我这个也不太清楚对不对,只是我个人的理解,如果有错误,希望各位大神能够指出来。

论坛徽章:
0
9 [报告]
发表于 2014-08-05 16:55 |只看该作者
再次谢谢大神,现在理解了呢,对于/regex1/,/regex2/范围内的替代问题,又做了下面的测试
  1. 01.xian@QA:~$ vi dat

  2. 02.

  3. 03.1 dat                                                     #6是address,p是function,下同

  4. 04.2 Desktop

  5. 05.3 dir1

  6. 06.4 dir2

  7. 07.5 Documents

  8. 08.6 Music                                                 #sed默认是自动输出的

  9. 09.6 Music                                                 #这一行是由命令p输出的

  10. 10.7 Pictures

  11. 11.8 Public

  12. 12.9 Templates

  13. 13.10 Videos

  14. xian@QA:~$ sed -n '/dir/,/Music/{s//replaced/p} ' dat
  15. 3 replaced1
  16. 6 replaced
复制代码
其中,dir作为范围的起始字符,只匹配了第一次出现的行,Music作为范围的结束字符,也是只匹配了第一次出现的行

对于add,/regex/范围的替代,做了下面测试
  1. xian@QA:~$ sed -n '6,/Music/{s/Music/replaced/p} ' dat
  2. 6 replaced                                                 #sed默认是自动输出的
  3. 6 replaced                                                 #这一行是由命令p输出的
  4. xian@QA:~$ sed -n '0,/Music/{s/Music/replaced/p} ' dat
  5. 6 replaced                                                 #sed默认是自动输出的
  6. xian@QA:~$
复制代码
当add代表的行中可以匹配到/regex/时,还是会出现匹配两次的情况,不知道下面的1,/regexp/是不是对于n,/regexp/都适用呢(n>0)??
  1. if addr2 matches the very first line of input the 0,/regexp/ form will consider it to end the range, whereas the 1,/regexp/ form will match the beginning of its range and hence make the range span up to the second occurrence of the regular expression
复制代码
回复 9# 欧阳西风


   

论坛徽章:
3
天蝎座
日期:2013-12-10 19:37:11酉鸡
日期:2014-08-04 20:05:38双鱼座
日期:2014-08-09 21:53:54
10 [报告]
发表于 2014-08-05 20:05 |只看该作者
回复 10# siyecaoliu


    我这儿测试使用addr,/regex/匹配时,也仅出现了一次匹配结果,不知道你的sed版本是什么?

另外,你刚刚引用的那句话,仅适用于1,/regex/. 其实0,/regex/与1,/regex/的主要区别应该是 首行匹配/regex/的情况,即:
如果是0,/regex/并且第一行能够匹配/regex/,那么不再做第二行的处理,也即这个范围到此结束。
如果是1,/regex/第一行不做匹配/regex/(即使实际是匹配的),该范围从第一行开始,直到下一次成功匹配/regex/结束。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP