2010-01-08 7 views
8

que tienen un conjunto de direcciones URL:regular express: cómo excluir múltiples grupos de caracteres?

/productos

/categorías

/clientes

Ahora decir los clientes se llamaba Juan, y yo quiero ayudar a John a llegar a su propia página de cuenta con una URL más corta:

before : /customers/john 
after : /john 

(nombres de clientes suponen son únicos)

Estoy tratando de encontrar una expresión regular despachador de manera adecuada todos los clientes pueden tener esta característica:

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

aquí es lo que tengo ahora (en PHP):

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

Esto no parece funcionar. ¿Alguien puede ayudarme?

+0

¡Todos a bordo del Regular Express! ¡Ciruelas pasas y avena! –

Respuesta

16

Lo que necesita aquí es un lookahead negativo assertion. Lo que quiere decir es "Quiero hacer coincidir cualquier cadena de caracteres, excepto estas cadenas en particular". Una aserción en una expresión regular puede coincidir con una cadena, pero no consume ningún carácter, lo que permite que el resto de tu expresión regular coincida. Puede especificar una aserción negativa envolviendo un patrón en (?! y ).

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

Tenga en cuenta que es posible que desee el siguiente lugar, si usted no permite que los nombres de los clientes que incluyen barras:

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

Está tratando de usar una clase de caracteres negada de forma incorrecta. Una clase de carácter negada dice 'no coinciden con los caracteres contenidos'. Lo que quieres decir es 'no coinciden si esto que especifiqué aquí existe'. Para hacer eso tienes que ser un poco más creativo. Probablemente necesite un poco de mirada negativa. No estoy 100% seguro del motor de expresiones regulares de php, pero algo similar debería funcionar.

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

así, de búsqueda hacia atrás negativo (?<! ...) diciendo que no coincide con el .+ si products o categories o admin preceden. Entonces eso está en un grupo sin captura (?: ...).

Consulte Regular Expression Advanced Syntax Reference para obtener ayuda adicional.

+0

Er, no necesitas ir tan elegante como lookbehind (y de hecho, no creo que funcione, ya que aún no has consumido esos caracteres), y las aserciones negativas siempre son no caputuring, porque bueno, son negativos; ¿Qué capturarían? –

+0

Gracias a la sugerencia de Brian, aquí hay una posible solución a su declaración: /^\/(.+)(? Shawn

+0

@Qberticus: mismo efecto, pero usar assertion es más intuitivo. – Shawn

6

Esto es totalmente la manera equivocada de resolver el problema, pero es posible expresar lookaheads negativos fijos sin utilizar lookaheads negativos. Espacio adicional para mayor claridad:

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

Wow. No estoy seguro de si debería impresionarme o molestarme. Sí, es posible hacer un look-look negativo en expresiones regulares. incluso si no hay azúcar sintáctica para ellos, jus t como es posible hacer coincidir una amplia gama de caracteres sin clases de caracteres. No estoy seguro de por qué querrías escribir '(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) 'en lugar de' [a-zA-Z] ', y tampoco estoy seguro de por qué querrías evitar aserciones negativas de búsqueda anticipada' (?!) '. –

+0

nah .. Simplemente estoy asustado. Creo que hay una mejor solución. Además, no es el fin del mundo. – Shawn

+4

Solo por diversión, realmente, ya que alguien más ya envió la respuesta correcta. – ephemient

Cuestiones relacionadas