一个包含某个单词但不包含另一个单词的字符串的正则表达式

153
我正在设置Google Analytics中的一些目标,需要一些正则表达式的帮助。
假设我有4个URL:
http://www.anydotcom.com/test/search.cfm?metric=blah&selector=size&value=1
http://www.anydotcom.com/test/search.cfm?metric=blah2&selector=style&value=1
http://www.anydotcom.com/test/search.cfm?metric=blah3&selector=size&value=1
http://www.anydotcom.com/test/details.cfm?metric=blah&selector=size&value=1

我想创建一个表达式,识别任何包含字符串selector=size但不包含details.cfm的URL。

我知道要查找不包含另一个字符串的字符串,可以使用以下表达式:

(^((?!details.cfm).)*$)

但是,我不确定如何添加selector=size部分。

任何帮助将不胜感激!

5个回答

205

这应该就可以了:

^(?!.*details\.cfm).*selector=size.*$

^.*selector=size.*$ 应该很清楚了。第一个部分 (?!.*details.cfm) 是一个负向预测:在匹配字符串之前,它会检查字符串不包含 "details.cfm"(在它之前有任意数量的字符)。


9
请参考http://www.regexr.com/,这是一个很好的测试这些表达式的方法。 - Joshua Pinter
总是忘记负向先行断言,而它非常有用。 - Alexei Blue
"http://www.anydotcom.com/test/search.cfm?metric=blah&selector=sized&value=1" =~ /^(?!.*details\.cfm).*selector=size.*$/ #=> 0 是错误的。(请注意字符串包含 "...selector=sized..."。)另外,为什么在末尾加上 .*$ - Cary Swoveland

5
^(?=.*selector=size)(?:(?!details\.cfm).)+$

如果您的正则表达式引擎支持占用量词(虽然我怀疑Google Analytics不支持),那么我想这将在处理大型输入集时表现更佳:
^[^?]*+(?<!details\.cfm).*?selector=size.*$

这假定selector=size总是在details.cfm之前,但在最后一个URL中并非如此。 - Kobi
只是想澄清一下,那不是我。我不明白为什么有人会对这里的两个答案进行负投票,它们都是正确的。 - Kobi
@Kobi:这应该是一个向前看的修正。哦,顺便说一下,我并不怀疑是你的负评。 - Tomalak

3

正则表达式可以使用(Perl语法):

`/^[(^(?!.*details\.cfm).*selector=size.*)|(selector=size.*^(?!.*details\.cfm).*)]$/`

这是一个损坏的正则表达式,方括号将所有模式序列转换为单个字符的组合。 - Wiktor Stribiżew

1

接受答案中的正则表达式存在问题。 它也会匹配abcselector=sizeselector=sizeabc等。

正确的正则表达式可以是^(?!.*\bdetails\.cfm\b).*\bselector=size\b.*$

regex101上的正则表达式解释:

enter image description here


2
虽然你没有错,但最初被接受的正则表达式满足了我的需求,因为你提供的示例不在可能字符串的集合中。 - Chris Stahl
我认为最好的做法是在所选答案上留下一条评论,说明需要注意词边界,并举例说明原因。首先,这只是一个小问题,可能是疏忽导致的。此外,任何查看所选答案的人可能不会看到你的回答,但他们会看到评论(@Kobi也会看到)。 - Cary Swoveland

0
我在寻找一种方法来避免在类似于OP和Kobi的解决方案的情况下对尾部使用--line-buffered,而Kobi的解决方案非常适合我。 在我的情况下,排除带有“bot”或“spider”的行,同时包括' / '(用于我的根文档)。
我的原始命令是:
tail -f mylogfile | grep --line-buffered -v 'bot\|spider' | grep ' / '

现在变成了(使用-P Perl开关):
tail -f mylogfile | grep -P '^(?!.*(bot|spider)).*\s\/\s.*$'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接