用正则表达式包含某个模式但排除另一个模式

5

我很难找到如何编写正则表达式来包含以指定短语开头的特定URL,而排除另一个。

我们想要包含以以下内容开头的页面:

/womens
/mens
/kids-clothing/boys
/kids-clothing/girls
/homeware

但我们希望排除任何URL中带有/sXXXXXXX的内容 - 其中X代表数字。

我已经编写了以下代码以匹配下面的URL,但它的行为非常奇怪。我应该使用lookaround或其他什么东西吗?

\/(womens|mens|kids\-clothing\/boys|kids\-clothing\/boys|homeware).*[^s[0-9]+].*

/homeware/bathroom/s2522424/4-tier-pastel-pop-drawers-approx-91cm-x25cm-x-28cm
/homeware/bathroom/towels-and-bathmats
/homeware/bathroom/towels-and-bathmats/s2506420/boutique-luxury-towels
/homeware/bathroom/towels-and-bathmats?page=3&size=36&cols=4&sort=&id=/homeware/bathroom/towels-and-bathmats&priceRange[min]=1&priceRange[max]=14
/homeware/bathroom?page=3&size=36&cols=4&sort=&id=/homeware/bathroom&priceRange[min]=1&priceRange[max]=35
/homeware/bedroom
/homeware/bedroom/bedding-sets
/homeware/bedroom/bedding-sets/s2471012/striped-reversible-printed-duvet-set
/homeware/bedroom/bedding-sets/s2472706/check-printed-reversible-duvet-set
/homeware/bedroom/bedding-sets/s2475332/union-jack-duvet-set
/kids-clothing/boys/shop-by-age/toddler-3mnths-5yrs/s2520246/boys-lollipop-slogan-t-shirt
/kids-clothing/boys/shop-by-age/toddler-3mnths-5yrs/s2520253/boys-2-pack-dinosaur-t-shirts
/kids-clothing/girls/great-value/sale?page=1&size=36&cols=4&sort=price.asc&id=/kids-clothing/girls/great-value/sale&priceRange[min]=0.5&priceRange[max]=7
/kids-clothing/girls/mini-shops/ballet-outfits
/kids-clothing/girls/shop-by-age/baby--newborn-0-18mths
/kids-clothing/girls/shop-by-age/baby--newborn-0-18mths/s2484120/3-pack-frill-pants-pinks
/kids-clothing/girls/shop-by-age/baby--newborn-0-18mths/s2504431/3-pack-l-s-bodysuit
/mens/categories/tops?page=5&size=36&cols=4&sort=&id=/mens/categories/tops&priceRange[min]=2&priceRange[max]=22.5
/mens/categories/trousers-and-chinos
/mens/categories/trousers-and-chinos/s2438566/easy-essential-cuffed-jogging-bottoms
/mens/categories/trousers-and-chinos/s2438574/easy-essential-cuffed-jogging-bottoms
/mens/categories/trousers-and-chinos/s2458939/regatta-zip-off-lightweight-outdoor-trousers

1
可能是重复问题:http://stackoverflow.com/questions/3792367/excluding-strings-using-regex?rq=1 - m4573r
你使用的是哪个正则表达式引擎? - Anderson Green
2个回答

2
你走在正确的道路上了。负向先行断言可以实现这个功能:
"^(?!.*\/s\d+)\/(womens|mens|kids\-clothing\/boys|kids\-clothing\/girls|homeware)\/.*"

^锚定字符串的开头。(?!.*\/s\d+)表示字符串中不能出现"/sXXXXXXX",其余部分匹配所需的起始标记。

之所以[^s[0-9]+]无效,是因为[^xyz]仅匹配一个字符。实际上,您要找的是任何不包含"s""[""0-9"组合的字符,后跟"]"。例如:"s[234[s]"

您需要将负向先行断言放在字符串的开头,这样就不会匹配任何内容。如果您将其放在\/(womens|mens|kids\-clothing\/boys|kids\-clothing\/girls|homeware)\/.*之后,您仍然会成功匹配"/sXXXXXXX"之前的所有内容。例如:对于数据的第一行,您会匹配"/homeware/bathroom/"。


太棒了,完美运行!非常感谢您的解释...我对环视如何工作有些困惑。 - Ryan

1
是的,您需要使用负向先行断言:
/^\/(womens|mens|kids\-clothing\/boys|kids\-clothing\/boys|homeware)(?:\/(?:(?!s\d+).)*)+$/gm

如果你一行一行比较,就不需要多行(m)标记。它可能表现奇怪是因为你把字符类(用方括号表示)嵌套在更多的方括号中,这是不起作用的;你不能嵌套字符类。这在 refiddle 上经过测试并有效。

这将对所有提供的输入都失败。 - Bennor McCarthy
否定。正如我所指出的,我在Refiddle上测试过了,它可以正常工作。你试过吗? - Adrian
是的,你说得对。我错过了你答案末尾的“+”。抱歉。+1。为自己辩护,我刚醒来。 - Bennor McCarthy

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