【问题标题】:regular express : how to exclude multiple character groups?正则表达式:如何排除多个字符组?
【发布时间】:2010-01-08 05:30:25
【问题描述】:

我有一组网址:

/产品

/类别

/客户

现在假设一位客户名叫 john,我想帮助 john 以更短的 url 访问他自己的帐户页面:

before : /customers/john
after  : /john

(假设客户名称是唯一的)

我正在尝试找出一个合适的正则表达式调度程序,以便所有客户都可以拥有此功能:

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

这是我现在得到的(在 PHP 中):

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

这似乎不起作用。有人可以帮帮我吗?

【问题讨论】:

    标签: regex


    【解决方案1】:

    你需要的是一个否定的前瞻assertion。你想说的是“我想匹配任何字符串,除了这些特定的字符串。”正则表达式中的断言可以匹配字符串,但它不消耗任何字符,从而允许这些字符与正则表达式的其余部分匹配。您可以通过在(?!) 中包装模式来指定否定断言。

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

    请注意,如果您不允许客户名称包含斜杠,您可能需要以下内容:

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

    【讨论】:

      【解决方案2】:

      这完全是解决问题的错误方法,但可以在不使用负前瞻的情况下表达固定的负前瞻。为清晰起见额外的间距:

      ^ (
      ( $ | [^/] |
        / ( $ | [^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] ))))))))))
      ) .* ) $
      

      【讨论】:

      • 哇。我不确定我是应该被感动还是被打扰。是的,可以在正则表达式中进行负前瞻,即使它们没有语法糖,就像可以在没有字符类的情况下匹配整个字符范围一样。不过,我不确定您为什么要写 (a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z) 而不是 [a-zA-Z],同样我不确定您为什么要避免负面的前瞻性断言 (?!)
      • 不...我只是害怕。我相信有更好的解决方案。此外,这不是世界末日。
      • 只是为了好玩,真的,因为其他人已经发布了正确的答案。
      • @Brian Campbell:信不信由你,有些正则表达式风格不支持前瞻。对于那些人来说,这是唯一的方法。看起来很吓人,但如果一切都失败了……+1
      【解决方案3】:

      您试图以错误的方式使用否定字符类。否定字符类表示“不匹配包含的字符”。您要说的是“如果我在此处指定的内容存在,则不匹配”。要做到这一点,你必须更有创意。可能需要一些负面的回顾。我不是 100% 确定 php 的正则表达式引擎,但类似的东西应该可以工作。

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

      所以,如果 productscategoriesadmin 在它前面,则否定后向 (?&lt;! ... ) 说不匹配 .+。然后是在一个非捕获组(?: ... )

      查看Regular Expression Advanced Syntax Reference 以获得更多帮助。

      【讨论】:

      • 呃,你不需要像lookbehind那样花哨(事实上,我认为这行不通,因为你还没有消耗这些字符),否定断言是总是不捕获,因为,嗯,它们是负面的;他们会捕捉到什么?
      • 感谢 Brian 的提示,这里有一个可能的解决方法:/^\/(.+)(?
      • @Qberticus:效果一样,但使用断言更直观。
      • 无论如何,我总是包括非捕获组。它是明确的,以防万一发生变化。 Lookbehind 并不花哨 (?! vs (?
      猜你喜欢
      • 2011-05-05
      • 2021-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      相关资源
      最近更新 更多