免费注册 查看新帖 |

Chinaunix

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

[文本处理] 请教sed高手如何使sed支持贪婪匹配 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-01-06 21:45 |只看该作者 |倒序浏览
请教sed高手:
http://bbs.chinaunix.net/thread-1453069-2-1.html
说: sed是否支持贪婪与懒惰匹配可以用 \< 或 \b表达式,
我用下面的命令,测试:
  1. echo "abc123abc" | sed -n -r 's/.*\<([0-9]*)[a-z]*/\1/p'
复制代码
输出:123abc
如果想让命令只输出:123,请问应该怎么写?
谢谢!

论坛徽章:
0
2 [报告]
发表于 2013-01-06 21:50 |只看该作者
  1. echo "abc123abc" | sed -n -r 's/[^0-9]*([0-9]*)[a-z]*/\1/p'
复制代码
Try this.

论坛徽章:
0
3 [报告]
发表于 2013-01-06 22:09 |只看该作者
本帖最后由 karlzheng_cu 于 2013-01-07 08:51 编辑
love_shift 发表于 2013-01-06 21:50
Try this.

请问:1.能否用 .*来匹配?2. \< 不是锚定一个单词的边界吗?为什么能阻止贪婪匹配?(在这里如果要用.*来匹配如何写?--有时前面的字符可能是汉字或其它的字符,如果只知道后面的是数字,.*最有通用性)

论坛徽章:
0
4 [报告]
发表于 2013-01-06 22:20 |只看该作者
回复 3# karlzheng_cu

这些都是正则表达式  你应该先学正则表达式 然后awk sed grep就容易懂了

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:51:162015年亚洲杯之阿曼
日期:2015-04-07 20:00:59
5 [报告]
发表于 2013-01-07 12:03 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
1
射手座
日期:2014-03-10 14:24:52
6 [报告]
发表于 2013-01-07 12:17 |只看该作者
zooyo 发表于 2013-01-07 12:03
echo 123


精彩哈哈

论坛徽章:
0
7 [报告]
发表于 2013-02-15 18:29 |只看该作者
回复 2# love_shift


  2 楼的答案是正确的,但是1楼解法错在哪里了呢?

论坛徽章:
6
摩羯座
日期:2013-08-24 10:43:10狮子座
日期:2013-08-25 10:27:06天秤座
日期:2013-09-11 20:28:44午马
日期:2014-09-28 16:06:0015-16赛季CBA联赛之八一
日期:2016-12-19 13:55:0515-16赛季CBA联赛之天津
日期:2016-12-20 14:01:23
8 [报告]
发表于 2013-02-15 19:39 |只看该作者
本帖最后由 cao627 于 2013-02-15 20:12 编辑

回复 1# karlzheng_cu


    sed  -r 's/.*\<([0-9]*)[a-z]*/\1/'

表达式的红色部分由于\<   的存在,为了使整个表达式不至于匹配失败,两个*只能从最大贪婪中做出妥协,直到让退到0。整个表达式免于了匹配失败。
于是整个表达式只由后半部的  [a-z]*匹配到
abc123abc
的红色abc
并且由于第二个*退到了0,所以\1为空
所以红色abc被替换为空
整个字符串变为
123abc

整个表达式等价于
  1. echo "abc123abc" | sed  -r 's/[a-z]*//'
复制代码

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-12-16 06:20:00
9 [报告]
发表于 2013-02-15 22:10 |只看该作者
目测是因为abc123abc里面\<没有把abc 123 abc鉴定为3个单词吧,人为加一个空格就可以,运行结果如下:
  1. [root@node1 work]# echo "abc 123abc" | sed -n -r 's/.*\<([0-9]*)[a-z]*/\1/p'
  2. 123
复制代码
如果要去123的话,把这个结果在sed一次好了,不过刚才测试了一下,如果123前面的不是abc而是中文,貌似第一步是得不到123abc的。
  1. [root@node1 work]# echo "中国123abc" | sed -n -r 's/.*\<([0-9]*)[a-z]*/\1/p'
  2. 中国123abc
复制代码

论坛徽章:
6
摩羯座
日期:2013-08-24 10:43:10狮子座
日期:2013-08-25 10:27:06天秤座
日期:2013-09-11 20:28:44午马
日期:2014-09-28 16:06:0015-16赛季CBA联赛之八一
日期:2016-12-19 13:55:0515-16赛季CBA联赛之天津
日期:2016-12-20 14:01:23
10 [报告]
发表于 2013-02-16 20:25 |只看该作者
本帖最后由 cao627 于 2013-02-16 21:19 编辑

回复 10# nathanielwen


     echo "中国123abc" | sed -n -r 's/.*\<([0-9]*)[a-z]*/\1/p'

之所以输出:
中国123abc
是因为.*\<([0-9]*)[a-z]*如果*取非0的话,这个模式根本匹配不了  中国123abc,所以*都取值0了

就好比
  1. echo "中国123abc" | sed -n -r 's/^[a-z]*/xxx/p'
  2. xxx中国123abc
  3. echo "中国123abc" | sed -n -r 's/^/xxx/p'
  4. xxx中国123abc
复制代码
echo "abc123abc" | sed -n -r 's/.*\<([0-9]*)[a-z]*/\1/p'
之所以输出:
123abc
是因为整个命令行等价于
echo "abc123abc" | sed -n -r 's/\<[a-z]*//p'  
原因我楼上解释过了,这里再强调下:
正则的*虽然贪婪,但总是尽最大努力作出妥协来保证匹配成功,直到退无可退 ,所以前两个*妥协到0。于是
echo "abc123abc" | sed -n -r 's/.*\<([0-9]*)[a-z]*/\1/p'
等价于
echo "abc123abc" | sed -n -r 's/.{0}\<([0-9]{0}) [a-z]*/\1/p'
最终等价于
echo "abc123abc" | sed -n -r 's/\<[a-z]*//p'   
对于中国123abc
最后一个*也只能妥协为0:
echo "中国123abc" | sed -n -r 's/\<[a-z]{0}//p'  
echo "中国123abc" | sed -n -r 's/\<//p'  

导致.{1,}\<([0-9]{1,})[a-z]*匹配不了abc123abc中国123abc的原因是\<
整个abc123abc就是一个单词,又怎么能在这个单词中用\<来界定一个单词的左边界?




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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP