regular express : how to exclude multiple character groups?

柔情痞子 提交于 2021-02-06 10:11:26

问题


I have a set of urls :

/products

/categories

/customers

Now say a customers is named john, and I want to help john to reach his own account page with a shorter url:

before : /customers/john
after  : /john

(suppose customer names are unique)

I'm trying to figure out a proper regex dispatcher so all customers can have this feature :

/marry
/james
/tony-the-red-beard

here is what I got now(in PHP) :

'/^\/([^(products|categories|admin)].+)$/' => /customers/$1

This doesn't seem to work. Anybody can help me?


回答1:


What you need here is a negative lookahead assertion. What you want to say is "I want to match any string of characters, except for these particular strings." An assertion in a regex can match against a string, but it doesn't consume any characters, allowing those character to be matched by the rest of your regex. You can specify a negative assertion by wrapping a pattern in (?! and ).

'/^\/(?!products|categories|admin)(.+)$/'

Note that you might want the following instead, if you don't allow customers names to include slashes:

'/^\/(?!products|categories|admin)([^/]+)$/'



回答2:


This is entirely the wrong way to go about solving the problem, but it is possible to express fixed negative lookaheads without using negative lookaheads. Extra spacing for clarity:

^ (
( $ | [^/] |
  / ( $ | [^pc] |
    p ( $ | [^r] |
      r ( $ | [^o] |
        o ( $ | [^d] |
          d ( $ | [^u] |
            u ( $ | [^c] |
              c ( $ | [^t] |
                t ( $ | [^s] ))))))) |
    c ( $ | [^au] |
      a ( $ | [^t] |
        t ( $ | [^e] |
          e ( $ | [^g] |
            g ( $ | [^o] |
              o ( $ | [^r] |
                r ( $ | [^i] |
                  i ( $ | [^e] |
                    e ( $ | [^s] )))))))) |
      u ( $ | [^s] |
        s ( $ | [^t] |
          t ( $ | [^o] |
            o ( $ | [^m] |
              m ( $ | [^e] |
                e ( $ | [^r] |
                  r ( $ | [^s] ))))))))))
) .* ) $



回答3:


You're trying to use a negated character class the wrong way. A negated character class says 'do not match the contained characters'. What you are wanting to say is 'do not match if this stuff I specified here exists'. To do that you have to a bit more creative. Probably need some negative lookbehind. I'm not 100% sure about php's regex engine but something similar to this should work.

/^\/(?<!(?:products|categories|admin))(.+)$/

so, negative lookbehind (?<! ... ) saying don't match the .+ if products or categories or admin precede it. Then that is in a non-capturing group (?: ... ).

Check out Regular Expression Advanced Syntax Reference for extra help.



来源:https://stackoverflow.com/questions/2025727/regular-express-how-to-exclude-multiple-character-groups

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!