Соберите части строки, представляющие теги <img>, в список в Java 8

Есть вариант использования, когда у меня есть длинное String, которое может содержать много <img> тегов. Мне нужно собрать весь тег изображения от начала (<img src = ") до закрытия (">) в списке.

Я написал регулярное выражение ("<img.*?\">"gm) для их выбора, но не знаю, как собрать их все в список.

например:

final String regex = "<img.*?\\\">";
final String string = "Hello World <img src=\"https://dummyimage.com/300.png/09f/777\"> \nMy Name <img src=\"https://dummyimage.com/300.png/09f/ff2\"> Random Text\nHello\nHello Random <img src=\"https://dummyimage.com/300.png/09f/888\"> \nMy Name <img src=\"https://dummyimage.com/300.png/09f/2ff\">adaad\n";
final String replace = "";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

final String result = matcher.replaceAll(replace); // Here, how can I collect all the image tags in a list

Вы можете использовать #start, #end и #group в классе Matcher, чтобы получить эту информацию. Это было бы вопросом повторения групп в вашем совпадении и добавления их в список самостоятельно. Обратите внимание, что если ваше регулярное выражение включает в себя более одного тега на группу (например, <img ...> ... </img>), вы столкнетесь с ограничениями регулярного выражения и, скорее всего, вам понадобится синтаксический анализатор html.

Rogue 15.11.2022 16:47

Лично я бы не стал изобретать парсеры html заново. Не надо и не сделаешь так, как те, кто их зарабатывает на жизнь

g00se 15.11.2022 16:50
jsoup.org
Basil Bourque 15.11.2022 17:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете просто сделать это:

final List<String> result = new ArrayList<>();
while (matcher.find()) {
     result.add(matcher.group());
}

и избавься от своего final String replace = "";

Ответ принят как подходящий

Java 8 — Pattern.splitAsStream()

Мы можем разделить данную строку, используя так называемые Lookaheads и Lookbehinds (для получения дополнительной информации см. ссылку, приведенную ниже):

  • (?<=.)(?=<) — соответствует положению между любым символом и открывающей угловой скобкой < (т. е. захватывает пустую подстроку между любым символом и началом тега).

  • (?<=>)(?=.) — соответствует позиции между закрывающей угловой скобкой > и любым символом.

public static final Pattern ANGLE_BRACKETS =
    Pattern.compile("(?<=.)(?=<)|(?<=>)(?=.)");

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

final String string = "Hello World <img src=\"https://dummyimage.com/300.png/09f/777\"> \nMy Name <img src=\"https://dummyimage.com/300.png/09f/ff2\"> Random Text\nHello\nHello Random <img src=\"https://dummyimage.com/300.png/09f/888\"> \nMy Name <img src=\"https://dummyimage.com/300.png/09f/2ff\">adaad\n";

List<String> imageTags = ANGLE_BRACKETS.splitAsStream(string)
    .filter(str -> str.strip().matches("<img[^<]+>")) // verifying that a string is a valid image tag
    .toList();
        
imageTags.forEach(System.out::println);

Ссылка на онлайн демо

Java 9 — Matcher.results()

В регулярном выражении вам нужно позаботиться об открывающей угловой скобке < (не кавычках), чтобы захваченная подстрока содержала только один тег:

public static final Pattern IMG_TAG = Pattern.compile("img[^<]+>");

Используя метод Java 9 Matcher.results(), мы можем создать поток MatchResult объектов, которые содержат информацию о захваченных последовательностях в заданной строке. И чтобы получить совпадающую подстроку, мы можем использовать MatchResult.group().

final String string = "Hello World <img src=\"https://dummyimage.com/300.png/09f/777\"> \nMy Name <img src=\"https://dummyimage.com/300.png/09f/ff2\"> Random Text\nHello\nHello Random <img src=\"https://dummyimage.com/300.png/09f/888\"> \nMy Name <img src=\"https://dummyimage.com/300.png/09f/2ff\">adaad\n";
    
List<String> imageTags = IMG_TAG.matcher(string).results() // Stream<MatchResult>
    .map(MatchResult::group)                               // Stream<String>
    .toList();
        
imageTags.forEach(System.out::println);

Вывод:

<img src = "https://dummyimage.com/300.png/09f/777">
<img src = "https://dummyimage.com/300.png/09f/ff2">
<img src = "https://dummyimage.com/300.png/09f/888">
<img src = "https://dummyimage.com/300.png/09f/2ff">

Ссылка на онлайн демо

Не могли бы вы также предоставить отчеты об импорте?

Nitin Kumar 15.11.2022 17:03

@NitinKumar Конечно, вот ссылка на Online Demo (все необходимые импорты указаны вверху).

Alexander Ivanchenko 15.11.2022 17:10

@NitinKumar Я понял, почему вы просили об импорте. Matcher.results() был добавлен с Java 9 (если вы используете Java 8, он будет недоступен). Я предоставил альтернативное решение, совместимое с Java 8, на основе Pattern.splitAsStream() (через минуту я объясню, как оно работает).

Alexander Ivanchenko 15.11.2022 17:30

Другие вопросы по теме