2010-01-08 17 views
8

Mam zestaw adresów URL:regularne wyrażenie: jak wykluczyć wiele grup znaków?

/Produkty

/kategoria

/klientów

teraz powiedzieć klientom o nazwie John, i chcę pomóc Janowi przejdź na stronę swojego konta z krótszym adresem:

before : /customers/john 
after : /john 

(nazwy przypuszczać klientów są unikatowe)

Próbuję wymyślić odpowiedniego dyspozytora regex więc wszyscy klienci mogą mieć tę funkcję:

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

tutaj jest to, co mam teraz (w PHP):

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

To nie działa. Ktoś może mi pomóc?

+0

Wszystko na pokładzie Regular Express! Śliwki i płatki owsiane! –

Odpowiedz

16

To czego potrzebujesz tutaj, to przeczenie z wyprzedzeniem assertion. To, co chcesz powiedzieć, to "Chcę dopasować dowolny ciąg znaków, z wyjątkiem tych konkretnych ciągów". Asercja w wyrażeniu regularnym może być zgodna z ciągiem znaków, ale nie zużywa żadnych znaków, co pozwala dopasować te znaki do reszty twojego regex. Można określić negatywną asercję, zawijając wzorzec w (?! i .

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

Zauważ, że możesz chcieć następujące zamiast, jeśli nie pozwalają klientom na nazwy zawierają ukośników:

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

Próbujesz użyć błędnej klasy znaków w niewłaściwy sposób. Zanegowana klasa znaków mówi "nie pasuje do zawartych znaków". To, co chcesz powiedzieć, to "nie pasuj, jeśli te rzeczy, które tu podałem, istnieją". Aby to zrobić, musisz nieco bardziej kreatywny. Prawdopodobnie potrzebujesz jakiegoś negatywnego spojrzenia. Nie jestem w 100% pewny co do silnika regex php, ale coś podobnego powinno działać.

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

tak, negatywne lookbehind (?<! ...) powiedzenie nie odpowiadają jeśli .+products lub categories lub admin poprzedzać go. Następnie znajduje się w niezapewniającej się grupie (?: ...).

Aby uzyskać dodatkową pomoc, sprawdź numer Regular Expression Advanced Syntax Reference.

+0

Er, nie musisz iść tak fantazyjnie jak lookbehind (i faktycznie, nie sądzę, że to zadziała, skoro nie wykorzystałeś jeszcze tych znaków), a negatywne twierdzenia są zawsze niekapitulujące, ponieważ, cóż, są negatywne; co by złapali? –

+0

Dzięki podpowiedzi Briana, jest możliwe, że poprawka do Twojego oświadczenia: /^\/(.+)(? Shawn

+0

@Qberticus: ten sam efekt, ale korzystanie z asercji jest bardziej intuicyjne – Shawn

6

Jest to całkowicie niewłaściwy sposób, aby przejść o rozwiązywaniu problemu, ale możliwe jest wyrażanie stałych ujemnych uprzedzeń bez użycia ujemnego wyprzedzenia. Dodatkowe odstępy dla większej przejrzystości:

^ (
($ | [^/] | 
/($ | [^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, nie jestem pewien, czy powinienem być pod wrażeniem, czy przeszkadzać. Tak, możliwe jest wykonywanie ujemnego uprzedzenia w wyrażeniach regularnych, nawet jeśli nie ma dla nich cukru syntaktycznego, tak t jak to możliwe, aby dopasować cały zakres znaków bez klas postaci. Nie wiem, dlaczego chciałbyś napisać "(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) 'zamiast' [a-zA-Z] ', i podobnie nie jestem pewien, dlaczego chciałbyś uniknąć negatywnych asercji z wyprzedzeniem" (?!) '. –

+0

nah .. Po prostu się boję. Uważam, że istnieje lepsze rozwiązanie. Poza tym to nie koniec świata. – Shawn

+4

Dla zabawy, naprawdę, ponieważ ktoś inny już opublikował prawidłową odpowiedź. – ephemient