用正则表达式找出不包含连续字符串abc的单词
[^abc]表示不包含a、b、c中任意字符, 我想实现不包含字符串abc应该如何写表达式?就我自己而言,这个问题最简单的解决方法是使用编程语言的配合,找出那些包含abc的,剩下的就是不包含的了——懒人的风格。但我写的是教程,读者未必都有编程的基础,有些只是使用一些工具从txt文档中抽取出一些信息,所以要回答还是必须完全通过正则表达式来完成。
于是打开了RegexTester,开始试验,先是试了使用((?'test'abc)|.)*(?(test)(?!))(含意是:查找abc,或任意的字符,如果找到了abc,就把它存入命名为test的组里,到最后检查test组里是否有内容,如果有就匹配失败,相关说明见教程),结果是"abc","aabc","abcd","aa"都能通过测试,看来是到最后测试到test组存在后又回溯了,此解决方案不可行。
然后又试了(.(?!abc))*(找出所有后面不是abc的字符),结果是"abc","abcd"通过测试,"aabc"则只截取了后面的"abc",显然不行。
那加强条件试试:((?<!abc).(?!abc))*(找出所有前面和后面都不是abc的字符),结果是所有包含abc的字符串都只截取了里面的"abc",不包含abc的则直接通过。
现在看来有点戏了,但是怎么把那些内部包含abc的字符串过滤掉呢?这个问题换句话说也就是怎么匹配整体而不是部分呢?现在需要明确用户的需求了:如果用户想要找的是单词,那就在表达式的两端加上\b,如果要找的是行,就加上^和$。由于用户的问题没有明确说明,我就当作是单词吧。
于是等到了这样的表达式:\b((?<!abc).(?!abc))*\b,经过测试,这个表达式能匹配所有不包含abc的单词,以及单词abc。
怎么排除单词abc?经过一番思考,最后我认为判断单词是否以a开头的方式最为方便:\b(a(?!bc)|[^a](?!abc))((?<!abc).(?!abc))*\b(要么以后面不是bc的a开头,要么不以a开头,除了开头后面所有的字符必须前面和后面都不是abc)。经过测试,完全满足要求,Bingo!
使用正则表达式查找不包含连续字符串abc的单词,最终结果:\b(a(?!bc)|[^a](?!abc))((?<!abc).(?!abc))*\b
----------------
更新:根据maple的评论,更简洁的作法是:\b((?!abc)\w)+\b
评论
#1楼 2007-03-26 13:16 maple[未注册用户]
用这个不也可以么?
((?!abc).)*? 回复 引用
#2楼[楼主] 2007-03-26 14:12 deerchao
@maple
我试了一下,但是((?!abc).)*?好像什么也匹配不到吧? 回复 引用 查看
#3楼 2007-03-26 15:54 maple[未注册用户]
两头加上\b
和你的表达式结果差不多
不过要匹配出单个单词,还需要修改 回复 引用
#4楼 2007-03-26 15:57 maple[未注册用户]
不好意思,应该是
\b((?!abc).)*\b
呵呵,多写了个问号 回复 引用
#5楼 2007-03-26 16:18 maple[未注册用户]
再试试这个表达式吧
\b((?!abc)\S)+?\b
不知道我对题意的理解对不对,这个应该可以匹配出不包含abc的单词,当然abc这个单词也会排除 回复 引用
#6楼[楼主] 2007-04-02 10:56 deerchao
不错,您的这个表达式能达到同样的效果,而且更简洁。 回复 引用 查看
#7楼 2007-04-04 11:43 apple[未注册用户]
您好,受益匪浅,但是我想匹配3-5个以字母或数字开头的字串,其中不包括http,这样写却什么也匹配不到,请教!!
/^[a-zA-Z0-9]{3,5}b((?!http)\S)+?$/ 回复 引用
#8楼[楼主] 2007-04-04 14:17 deerchao
您的表达式中间是不是多了一个b?
如果前面3-5个字母或数字也不能包含http,你可以使用:
^((?!http)[a-zA-Z0-9]){3,5}((?!http)\w)*$
如果前面可以包含http你可以使用:
^([a-zA-Z0-9]){3,5}((?!http)\w)*$
注:我是使用.Net的引擎进行测试的,也许在javascript引擎下结果不同。 回复 引用 查看
#9楼 2007-04-04 15:31 apple[未注册用户]
非常感谢你及时的回复,.Net的引擎有点不同,呵呵,不行,不过楼上的朋友给我了一点启发:\b((?!http)\S)+?\b;但是如何限定长度呢?? 回复 引用
#10楼[楼主] 2007-04-04 15:41 deerchao
我试了一下,javascript应该也可以啊:
test.htm
<script>
var valid="abcdefgh";
var invalid="acdsihttp";
var reg=/^((?!http)[a-zA-Z0-9]){3,5}((?!http)\w)*$/ ;
alert(reg.test(valid));
alert(reg.test(invalid));
</script> 回复 引用 查看
#11楼 2007-10-22 23:50 Felix
请教一个困扰我多次的问题,虽然类似,但我硬是没搞出来
已知:<[^>]+>可以匹配所有HTML标签,从而通过替换标签内容去掉这些标签形成纯粹的文本
但我想在匹配替换时排除<img /> 和 <a >xxx</a> 这两个标签从而让其在HTML文档中得到保留,却不知如何来写,希望能帮我研究研究,不胜感激!! 回复 引用 查看
#12楼[楼主] 2007-10-23 02:41 deerchao
@Felix
<(?!(/?(img|a)\b))[^>]*>
匹 配<html><a href="#">xxx</a><img /> <img></img><div id="aaa">xyz</div></html>的结果:
<html>
<div id="aaa">
</div>
</html> 回复 引用 查看
#13楼 2007-10-23 10:45 Felix
楼主真是非常的生猛,测试通过了,感谢!! 回复 引用 查看
#14楼 2007-10-23 11:41 Felix
楼主能否加我的MSN或Gtalk有事相商
lf1981##msn、com
Gtalk同理 回复 引用 查看
#15楼 2007-11-27 12:58 蜜桃[未注册用户]
有用!但是看不懂
欢迎来蜜桃玩
http://www. 回复 引用
#16楼 2008-04-19 13:51 sonic_andy[未注册用户]
([^a]|a[^b]|ab[^c]) 回复 引用
#17楼 2008-05-29 10:43 初学者ZXYLXW[未注册用户]
如果我想找出字符串中有abc,但排除有@abc的如何做呢?
比如说在.NET使用ACCESS"伪储存过程"中
我想替换 "abc" = "@abc" 中前面一个abc为"中文字段名"
变成 "中文字段名" = "@abc" ,请指教! 回复 引用
#18楼 2008-08-18 11:54 booker[未注册用户]
你好博主,我用用vim处理log,现在我想只保留用户名是TEMP的log记录,可是VIM中好像没有?!这样的正则表达式,我用:
/^.* \(TEMP\)\{0}.*$
结果无法匹配,不知道博主有没有什么好办法?谢谢 回复 引用
#19楼 2008-09-16 15:36 Yvon[未注册用户]
正在学习中,谢谢指点 回复 引用
#20楼 2008-12-29 10:42 fox33333[未注册用户]
那如果查找
werewre 123 werewr abc789 23342s112
wereww 123 2345fdfd 789 343242sdfd
如要匹配
包含123后跟任意字符 然后包含789 但是不包含连续的字符abc 这样如何写呢? 回复 引用
#21楼 2009-01-05 23:14 disss[未注册用户]
请教了
如果想选中不包括abc的行应该如何写 回复 引用
#22楼 2009-01-05 23:19 disss[未注册用户]
文本中如何实现
只保留含有abc或45678的行 回复 引用
#23楼 2009-03-25 14:37 regex[未注册用户]
昨天遇到这样的页面代码:
<!-- AAAA <!-- BBBB --> CCCC--> DDDD <!-- EEEE -->
想把<!-- -->的东西去掉。怎么写呢?
'<!--((?!(<!--|-->)).)*-->'sm
写了一个,这个可以处理(需要循环调用,一次去一层)。但是当匹配内容超过3000字节,就down掉了。。。
今天又遇到
<body><tr><td>不要我<div>抓我吧</div></td></tr></body>
想获得div,td,body最近一层里面的内容
/<(?:td|div|body|style|script)[^>]*>(.*?)/is
结果一看还是不行,获得是整个body感觉没有贪婪成功啊。。他获得的是body里的全部内容。
希望LZ帮忙看看,最好在给我发个email。谢啦! 回复 引用
#24楼 2009-07-29 11:31 qiufeng[未注册用户]
楼主
如果是想匹配不包含“//”的字符串呢 ,好像这个不能个实现啊
望楼主指点! 谢谢 回复 引用
#25楼 2009-08-08 00:49 Kevin Yang[未注册用户]
@qiufeng
可以参考我这篇文章,用于日志分析中排除包含特定字符串的条目。
http://www./2009/08/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%89%BE%E5%87%BA%E4%B8%8D%E5%8C%85%E5%90%AB%E7%89%B9%E5%AE%9A%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E6%9D%A1%E7%9B%AE.html
写这篇文章的时候参考了lz文章中的一些东西。 回复 引用
#26楼 2009-09-05 16:30 FeeLiN[未注册用户]
判断不包含字符串abc的很简单啊
难的是怎么判断不等于字符串abc 回复 引用
#27楼 2009-10-15 11:35 amenlv[未注册用户]
问个问题,为啥(\d+):\1 不能匹配11:22?
我想把文本中的时间找出来,比如10:22:35,但是这个\1的后向引用似乎没有效果啊~~~求解! 回复 引用
#28楼 2010-09-26 17:57 slow7777
!
在楼主翻译的正则表达式30分钟入门教程里Ctrl+F:abc第一个就是答案.
楼主你辜负了我对你的景仰- -|| 回复 引用 查看
#29楼 2011-01-23 15:46 alswl
@slow7777
- -#
啊~居然~ 回复 引用 查看
#30楼 2011-02-23 15:16 NewSea.
好文.正找到这. 回复 引用 查看
#31楼 2011-04-14 13:30 忧忧夏天
试了下这个\b[^a]*[^b]*[^c]*\b
只要不同时存在a,b,c就能匹配出来,不知道可以不
回复 引用 查看