Подтвердить что ты не робот

Java - Лучший способ захватить ВСЕ строки между двумя строками? (Регулярное выражение?)

Этот вопрос давно искал меня, но по сути я ищу наиболее эффективный способ захватить все строки между двумя строками.

То, как я делал это уже много месяцев, - это использовать кучу временных индексов, строк, подстрок, и это действительно беспорядочно. (Почему Java не имеет собственный метод, например String substring(String start, String end)?

Скажем, у меня есть строка:

abcabc [pattern1]foo[pattern2] abcdefg [pattern1]bar[pattern2] morestuff

Конечной целью будет вывод foo и bar. (И позже будет добавлен в JList)

Я пытаюсь включить regex в .split(), но не был успешным. Я пробовал синтаксис с помощью * и ., но я не думаю, что мое намерение особенно важно, поскольку .split() использует только один аргумент для разделения.

В противном случае я думаю, что другой способ - использовать классы Pattern и Matcher? Но я действительно нечеткий по соответствующей процедуре.

4b9b3361

Ответ 1

Вы можете создать регулярное выражение для этого:

// pattern1 and pattern2 are String objects
String regexString = Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2);

Это будет обрабатывать текст pattern1 и pattern2 как литерал, а текст между шаблонами будет записан в первом группа захвата. Вы можете удалить Pattern.quote(), если хотите использовать регулярное выражение, но я не ничего не гарантирую, если вы это сделаете.

Вы можете добавить некоторую настройку того, как должно совпадать, добавив флаги в regexString.

  • Если вы хотите использовать совместимое с Unicode кодирование без учета регистра, добавьте (?iu) в начале regexString или поставьте флаг Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE в Pattern.compile.
  • Если вы хотите захватить контент, даже если две строковые строки отображаются по строкам, добавьте (?s) до (.*?), то есть "(?s)(.*?)", или поставьте Pattern.DOTALL в Pattern.compile.

Затем скомпилируйте регулярное выражение, получив объект Matcher, проведите по ним и сохраните их в List (или любой Collection, это зависит от вас).

Pattern pattern = Pattern.compile(regexString);
// text contains the full text that you want to extract data
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
  String textInBetween = matcher.group(1); // Since (.*?) is capturing group 1
  // You can insert match into a List/Collection here
}

Код тестирования:

String pattern1 = "hgb";
String pattern2 = "|";
String text = "sdfjsdkhfkjsdf hgb sdjfkhsdkfsdf |sdfjksdhfjksd sdf sdkjfhsdkf | sdkjfh hgb sdkjfdshfks|";

Pattern p = Pattern.compile(Pattern.quote(pattern1) + "(.*?)" + Pattern.quote(pattern2));
Matcher m = p.matcher(text);
while (m.find()) {
  System.out.println(m.group(1));
}

Обратите внимание: если вы ищете текст между foo и bar в этом входе foo text foo text bar text bar с помощью метода выше, вы получите одно совпадение, которое равно  text foo text .

Ответ 2

Здесь однострочный, который делает все:

List<String> strings = Arrays.asList( input.replaceAll("^.*?pattern1", "")
    .split("pattern2.*?(pattern1|$)"));

Пробой:

  • Удалить все до шаблона1 (требуется, чтобы в конечном итоге не была пустая строка)
  • Разделить на вход (не жадный .*?) между pattern2 и pattern1 (или конец ввода)
  • Используйте метод утилиты Arrays.asList() для создания List<String>

Вот несколько тестовых кодов:

public static void main( String[] args ) {
    String input = "abcabc pattern1foopattern2 abcdefg pattern1barpattern2 morestuff";
    List<String> strings = Arrays.asList( input.replaceAll("^.*?pattern1", "").split("pattern2.*?(pattern1|$)"));
    System.out.println( strings);
}

Вывод:

[foo, bar]

Ответ 3

Попробуйте следующее:

String str = "its a string with pattern1 aleatory pattern2 things between pattern1 and pattern2 and sometimes pattern1 pattern2 nothing";
Matcher m = Pattern.compile(
                            Pattern.quote("pattern1")
                            + "(.*?)"
                            + Pattern.quote("pattern2")
                   ).matcher(str);
while(m.find()){
    String match = m.group(1);
    System.out.println(">"+match+"<");
    //here you insert 'match' into the list
}

Он печатает:

> aleatory <
> and <
> <