2008-09-04 10 views
16

Szukam wyrażeń regularnych, które będą pasować do ciągu znaków, który zaczyna się od jednego podciągu i nie kończy się na określonym podciągu.Regex, aby dopasować do czegoś, co nie jest określonym podciągiem

Przykład:

// Updated to be correct, thanks @Apocalisp 
^foo.*(?<!bar)$ 

powinien pasować wszystko, co zaczyna się od "foo" i nie kończy się "bar". Wiem o składni [^ ...], ale nie mogę znaleźć niczego, co zrobi to dla łańcucha zamiast pojedynczych znaków.

Próbuję zrobić to specjalnie w odniesieniu do regex Java, ale już wcześniej to robiłem, więc odpowiedzi na inne silniki regex również byłyby wspaniałe.

Dzięki @Kibbee za sprawdzenie, czy działa to również w języku C#.

+0

jak wspomniałem poniżej - regexp w pytaniu do ciągu wejściowego "foo123bar" to będzie pasował "foo12" - mam nadzieję, że to pożądane zachowanie. – Dmitry

Odpowiedz

9

myślę, że w tym przypadku chcesz negatywny lookbehind, tak:

foo.*(?<!bar) 
1

Nie jestem zaznajomiony z regex Java, ale dokumentacja dla Pattern Class sugerowałaby, że mógłbyś użyć (?! X) dla przechwytywania negatywnej negacji o zerowej szerokości (szuka czegoś, co nie jest X w tym postision, bez przechwytywania go jako odwołania wstecznego). Więc można zrobić:

foo.*(?!bar) // not correct 

Aktualizacja: prawo Apocalisp jest, chcesz negatywny lookbehind. (sprawdzasz, że to, co pasuje do *. nie kończy się na taktach)

+0

Problem z tym rozwiązaniem polega na tym, że dla łańcucha wejściowego "foo123bar" będzie pasować "foo12" - mam nadzieję, że to pożądane zachowanie. – Dmitry

0

Jak powiedzieli inni komentatorzy, potrzebujesz ujemnego wyprzedzenia. W Javie można użyć tego wzoru:

"^first_string(?!.?second_string)\\z" 
  • ^- gwarantuje, że łańcuch zaczyna first_string
  • \ Z - gwarantuje, że łańcuch kończy się second_string
  • - środki (second_string?.?) że first_string nie może być stosowana przez second_string
1
odpowiedź

zweryfikowane @ Apocalisp w użyciu:

import java.util.regex.Pattern; 
public class Test { 
    public static void main(String[] args) { 
    Pattern p = Pattern.compile("^foo.*(?<!bar)$"); 
    System.out.println(p.matcher("foobar").matches()); 
    System.out.println(p.matcher("fooBLAHbar").matches()); 
    System.out.println(p.matcher("1foo").matches()); 
    System.out.println(p.matcher("fooBLAH-ar").matches()); 
    System.out.println(p.matcher("foo").matches()); 
    System.out.println(p.matcher("foobaz").matches()); 
    } 
} 

To wyjście na właściwe odpowiedzi:

false 
false 
false 
true 
true 
true 
Powiązane problemy