2012-06-20 7 views
26

Я пытаюсь создать два регулярных выражения, которые будут соответствовать URI. Эти URI имеют формат: /foo/someVariableData и /foo/someVariableData/bar/someOtherVariableDataJava regex: Negative lookahead

Мне нужно два регулярных выражения. Каждый из них должен соответствовать одному, но не другому.

Режимы, из которых я первоначально придумал: /foo/.+ и /foo/.+/bar/.+ соответственно.

Я думаю, что второе регулярное выражение прекрасно. Он будет соответствовать только второй строке. Однако первое регулярное выражение соответствует обоим. Итак, я начал играть (в первый раз) с негативным взглядом. Я разработал регулярное выражение /foo/.+(?!bar) и установить следующий код, чтобы проверить его

public static void main(String[] args) { 
    String shouldWork = "/foo/abc123doremi"; 
    String shouldntWork = "/foo/abc123doremi/bar/def456fasola"; 
    String regex = "/foo/.+(?!bar)"; 
    System.out.println("ShouldWork: " + shouldWork.matches(regex)); 
    System.out.println("ShouldntWork: " + shouldntWork.matches(regex)); 
} 

И, конечно, оба они полны решимости true.

Кто-нибудь знает, что я делаю неправильно? Мне не нужно обязательно использовать негативный взгляд, мне просто нужно решить проблему, и я думаю, что негативный взгляд может быть одним из способов сделать это.

Спасибо,

ответ

51

Try

String regex = "/foo/(?!.*bar).+"; 

или, возможно,

String regex = "/foo/(?!.*\\bbar\\b).+"; 

, чтобы избежать ошибок на пути, типа /foo/baz/crowbars, которые я предполагаю, что вы хотите, чтобы регулярное выражение для соответствия.

Объяснение: (без двойных обратных косых черт, необходимых Java строк)

/foo/ # Match "/foo/" 
(?! # Assert that it's impossible to match the following regex here: 
.* # any number of characters 
\b # followed by a word boundary 
bar # followed by "bar" 
\b # followed by a word boundary. 
)  # End of lookahead assertion 
.+ # Match one or more characters 

\b, «слово границы якорного», соответствует пустому пространству между алфавитно-цифровым символом и не алфавитен-цифровым символом (или между началом/концом строки и символом alnum). Поэтому он соответствует до b или после r в "bar", но он не соответствует w и b в "crowbar".

Protip: Посмотрите на http://www.regular-expressions.info - отличный учебник по регулярному выражению.