2016-04-22 3 views
1

мне нужна помощь по извлечению несколько слов из этого предложения:Замена этим шаблоном не работает, как я ожидал бы, что не так?

String keywords = "I like to find something vicous in somewhere bla bla bla.\r\n" + 
      "https://address.suffix.com/level/somelongurlstuff"; 

И мой соответствующий код выглядит примерно так:

keywords = keywords.toLowerCase(); 
    regex = "(I like to find)(.*)(in)(.*)(\\.){1}(.*)"; 
    regex = regex.toLowerCase(); 
    keywords = keywords.replaceAll(regex, "$4 $2"); //"$4 $2"); 

И я хочу, чтобы извлечь слова между find и in и между in и первая точка. однако, поскольку URL-адрес имеет несколько точек, начинает происходить какой-то странный материал, и я получаю то, что мне нужно, плюс URL-адреса, которые заменяются пустыми местами. Я хочу, чтобы URL-адрес ушел, потому что в моем случае он должен совпадать с (.*), и мне нужна только одна точка после моих слов с (\\.){1}, поэтому мне интересно, что там происходит? Есть идеи?

Добавив (?s) или удалив все новые строковые символы в строке перед сопоставлением по регулярному выражению, вы получите что-то вроде: somewhere bla bla bla address suffix something vicious, так что проблема с URL-адресом, не оставив там точки, остается.

Это НЕ только о соответствии многострочного текста.

+0

Добавить '(? S)' перед шаблоном, чтобы включить режим DOTALL и заставить '.' соответствовать любому символу, включая новую строку. И удалите '{1}', что является избыточным. –

+0

@ WiktorStribiżew это не решает проблему, и это не имеет много общего с другим вопросом, на который вы заявили, что этот вопрос является дубликатом. Добавляя (? S) или удаляя все новые строковые символы в строке перед сопоставлением в регулярном выражении, вы получаете что-то вроде: «где-то bla bla bla https: // адрес суффикса что-то порочное», поэтому проблема с URL-адресом, не имея точек остался там ... –

+0

Ну, ваш вопрос звучит довольно нечетко (может быть, форматирование может помочь?). Я думаю, вам просто нужны как DOTALL, так и ленивые соответствия: ['(? S) (мне нравится искать) (. *) (In) (. *?) (\.) (. *)'] (Https: // regex101.com/r/zZ2hG7/1). Или ['(мне нравится искать) (. *) (In) ([^.] *) (\.) (. *)'] (Https://regex101.com/r/zZ2hG7/2). –

ответ

0

Вам нужно две вещи для исправления: 1) добавить модификатор DOTALL, так как у вас есть текст, который охватывает несколько строк, и 2) использовать ленивое совпадение точек или - более эффективно - отрицательный класс символов [^.] для соответствия символам до первого . после in:

(?s)(I like to find)(.*)(in)([^.]*)(\.)(.*) 
           ^^^^^^^ 

regex demo См

Однако, лучшим вариантом было бы this one:

(?s)(I like to find)(.*?)(in)([^.]*)(\.)(.*) 

Недостаточный (ленивый) квантификатор заставляет двигатель соответствовать как можно меньшему количеству символов между лениво квантифицированным подшаблоном и следующим подшаблоном. Если мы используем .* до (in), произойдет обратное отслеживание, то есть целая строка после того, как "I like to find " будет захвачен двигателем регулярного выражения, а затем двигатель переместится назад и ищет последниеin. Таким образом, использование .*? будет соответствовать , начиная сin.

Вместо [^.]* вы можете использовать . с неохотой квантора *? совпасть с первой точки, но это дороже, с точки зрения производительности, так как двигатель расширяет подмаскам на каждый провал попадается при попытке соответствовать строка с последующими подшаблонами.

Отметьте мой ответ для Perl regex matching optional phrase in longer sentence, чтобы понять, как работают жадные и ленивые (= неохотные) кванторы.

+0

Обратите внимание, что для выполнения первого регулярного выражения требуется 268 шагов, а второе - просто 85. Используйте ленивое соответствие, чтобы получить как можно меньше символов между двумя подшаблонами. –