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? Но я действительно нечеткий по соответствующей процедуре.
Ответы
Ответ 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 <
> <