免费注册 查看新帖 |

Chinaunix

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

[原创]论正则表达式的“贪婪”性  关闭 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2002-03-29 21:17 |只看该作者 |倒序浏览
正则表达式是具有贪婪性的,我们从下面这例谈起:
已知str="uid=100(guest) gid=100(others) groups=10(users),11(floppy)"
现在想要得到这个字符串中的第一个括号内的值,即guest该怎么办?假设$str的括号外的内容是不固定的,不能依据uid之类的关键字或空格去查找,所依据的只能是找第一对括号内的内容。

很自然的我们想到用sed,因为sed具有很强的模式匹配的功能,而且能够将匹配的部分内容强行记下来用于输出。这样,我们就会想:
echo $str|sed 's/模式串/\1/'
只要模式串写好了,在匹配的过程中把guest这个字符串抠出来,让sed记住,然后用\1输出就可以了。怎么写这个模式串?
.*想要匹配"uid=100"
(...)告诉sed要查找括弧内的文本
\(.*\)让sed记住匹配内容的常用手段,这里匹配的.*将来就能用\1取出来
.*想要匹配" gid=100(others) groups=10(users),11(floppy)"部分
于是我们就写成了echo $str|sed 's/.*(\(.*\)).*/\1/'
结果呢,得到的是"floppy",为什么?
正则表达式是有贪婪性的,它总是与最长的可能长度匹配,而且越是排在前面的通配符优先级越高。这一例,第一个.*可以匹配"uid=100(guest) gid=100(others) groups=10(users),11",仍然能保证后面通配符的匹配,那一对()匹配了floppy左右的括号,最后的.*自然是可有可无的,所以sed记住的就是floppy。
怎么办?我们必须打破正则表达式的贪吃性,用更明确的描述来实现这一点:
我们考虑如果在模式串中第一个.*中告诉sed这个.*是不能含有"("的,不久可以将.*限制到"uid=100"了吗?这个意思我们完全可以用[^(]*来表达,于是我们修订刚才的代码,变成:
echo $str|sed 's/[^(]*(\(.*\)).*/\1/'
似乎应该很好了,执行的结果却是"guest) gid=100(others) groups=10(users),11(floppy",为什么?
原来仍然是正则表达是的贪婪性在作怪,虽然我们有效的阻止了第一个.*的贪吃,但是我们对\(.*\)中的.*却未加限制,于是它尽可能匹配了"guest) gid=100(others) groups=10(users),11(floppy",还能保证后面&quot.*"的匹配性。我们再作限制,告诉sed,\(.*\)中的.*不能含有&quot",让它跨不过guest:
echo $str|sed 's/[^(]*(\([^)]*\)).*/\1/'
这回,输出结果终于是我们想要得"guest"了。

问题解决了,我们也了解了正则表达式(或说通配符)的贪婪性,于是就可以留个问题给大家,让大家自己体会体会:
怎么样取出str中第二对括号的内容"others"?
怎么样取出str中第三对括号的内容"users"?
怎么样取出str中第四对括号的内容"floppy"?(这个还用说吗,就利用正则表达式的贪婪性,我们最开始不就实现它了嘛)

论坛徽章:
0
2 [报告]
发表于 2002-03-30 18:25 |只看该作者

[原创]论正则表达式的“贪婪”性

[这个贴子最后由valentine在 2002/03/30 06:35pm 编辑]

又见michaelds的佳作。
俺来做作业。
str="uid=100(guest) gid=100(others) groups=10(users),11(floppy)"
echo $str|sed 's/[^(]*(\([^)]*\))[^(]*(\([^)]*\))[^(]*(\([^)]*\))[^(]*(\([^)]*\)
)/\2/'
上式得到others,把\2改成\3,\4可得到users和floppy。


~

论坛徽章:
0
3 [报告]
发表于 2006-05-18 10:55 |只看该作者
这个不是可以用awk么?
echo $str | awk -F'[()]' '{print $2" "$4" "$6" "$8}'

论坛徽章:
0
4 [报告]
发表于 2006-05-18 14:52 |只看该作者
贪婪地学习一哈子

论坛徽章:
0
5 [报告]
发表于 2006-05-19 09:16 |只看该作者

两大高手回来了,可喜可贺

两大高手回来了,可喜可贺

论坛徽章:
2
IT运维版块每日发帖之星
日期:2015-12-16 06:20:00数据库技术版块每日发帖之星
日期:2016-04-24 06:20:00
6 [报告]
发表于 2006-05-19 20:42 |只看该作者
不是说\?是消除贪婪性的?
怎么好象不行呢?

论坛徽章:
0
7 [报告]
发表于 2007-12-03 16:08 |只看该作者
呵呵  在perl中看到过有关正则表达式贪婪性的讲解...        有趣

论坛徽章:
0
8 [报告]
发表于 2008-05-07 14:06 |只看该作者
看完了支持下!!

论坛徽章:
0
9 [报告]
发表于 2008-05-10 22:41 |只看该作者
受教了

论坛徽章:
0
10 [报告]
发表于 2008-08-20 10:15 |只看该作者
不错不错,学习ing.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP