Как лучше всего найти определенные токены в строке (в Java)?

У меня есть строка с разметкой, которую мне нужно найти с помощью Java.

например.

string = abc<B>def</B>ghi<B>j</B>kl

desired output..

segment [n] = start, end

segment [1] = 4, 6
segment [2] = 10, 10

выглядит как регулярное выражение из пакета java.util.regex, плюс некоторые простые математические вычисления - способ продолжить это

pro 06.01.2009 13:30

или лучше, регулярное выражение типа <b> [^ <] + </b> для соответствия каждому сегменту

pro 06.01.2009 15:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
1 812
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Для этого прекрасно подойдут регулярные выражения.

Обратитесь к вашему JavaDoc для

  • java.langString.split ()
  • пакет java.util.regex
  • java.util.Scanner

Примечание. StringTokenizer - это не то, что вам нужно, поскольку он разбивается на символы, а не на строки - разделитель строк представляет собой список символов, любой из которых будет разделен. Это хорошо для очень простых случаев, например, для однозначного списка, разделенного запятыми.

StringTokenizer предоставит вам отдельные токены, если вы захотите разделить строку определенной строкой. Или вы можете использовать метод split () в String для получения отдельных строк. Чтобы получить разные массивы, вам нужно вставить регулярное выражение.

спасибо, Маркус .. для справки я нашел это .. StringTokenizer - это устаревший класс, который сохранен по соображениям совместимости, хотя его использование не рекомендуется в новом коде. Рекомендуется, чтобы любой, кто ищет эту функциональность, использовал вместо этого метод разделения String или пакет java.util.regex.

pro 06.01.2009 13:28

StringTokenizer разбивается на символы, а не на строки - разделитель строк представляет собой список символов, любой из которых будет разделен. Это хорошо для очень простых случаев, например, для однозначного списка, разделенного запятыми.

Lawrence Dol 06.01.2009 13:43

StringTokenizer принимает в качестве аргумента всю строку, и это не очень хорошая идея для больших строк. Вы также можете использовать StreamTokenizer

Еще нужно посмотреть Сканер.

Учитывая ваш пример, я думаю, что я бы использовал регулярное выражение, и особенно я бы посмотрел на функциональность группировки, предлагаемую Matcher.

Том

String inputString = "abc<B>def</B>ghi<B>j</B>kl";

String stringPattern = "(<B>)([a-zA-Z]+)(<\/B>)";

Pattern pattern = Pattern.compile(stringPattern);
Matcher matcher = pattern.matcher(inputString);

if (matcher.matches()) {

    String firstGroup  = matcher.group(1);
    String secondGroup = matcher.group(2); 
    String thirdGroup  = matcher.group(3);
}

это здорово - соответствие всего сегмента, а не только начальных / конечных тегов по отдельности

pro 06.01.2009 14:26

когда я пробовал ваше регулярное выражение в gskinner.com/RegExr, казалось, что сегменты не совпадают с чем-то простым, например, <B>. + </B> совпадает с первым <B> и последним </B>, так что это не способ

pro 06.01.2009 14:36

Вы . будет соответствовать чему угодно, поэтому он должен быть более строгим. Следовательно, я использую [a-zA-Z]. Я уверен, что после небольшой настройки и некоторого понимания того, чего можно ожидать между <B> и </B>, вы сможете это исправить.

Tom Duckering 06.01.2009 14:43

ah - заменить [a-zA-Z] на [a-zA-Z] +

Tom Duckering 06.01.2009 14:44

В этом регулярном выражении не должно быть обратной косой черты. Помещая их перед каждой круглой скобкой, вы говорите регулярному выражению, чтобы оно соответствовало буквальным скобкам. Тот, что находится перед косой чертой, ничего не вредит, но в этом нет необходимости.

Alan Moore 06.01.2009 16:00

Алан, ты прав. Я думаю, они вам понадобятся для какой-то другой реализации регулярного выражения. Мне нужна дополнительная обратная косая черта для прямой косой черты, чтобы сообщить Java, что обратная косая черта является буквальной. Что за палава. :)

Tom Duckering 06.01.2009 16:47

Это немного «грубая сила» и делает некоторые предположения, но это работает.

public class SegmentFinder
{

    public static void main(String[] args)
    {
        String string = "abc<B>def</B>ghi<B>j</B>kl";
        String startRegExp = "<B>";
        String endRegExp = "</B>";
        int segmentCounter = 0;
        int currentPos = 0;
        String[] array = string.split(startRegExp);
        for (int i = 0; i < array.length; i++)
        {           
            if (i > 0) // Ignore the first one
            {
                segmentCounter++;
                //this assumes that every start will have exactly one end
                String[] array2 = array[i].split(endRegExp);
                int elementLenght = array2[0].length();
                System.out.println("segment["+segmentCounter +"] = "+ (currentPos+1) +","+ (currentPos+elementLenght) );
                for(String s : array2)
                {
                    currentPos += s.length();  
                }
            }
            else
            {
                currentPos += array[i].length();                
            }
        }
    }
}

Ваш ввод похож на ваш пример, и вам нужно поместить текст между определенными тегами? Тогда простая строка StringUtils.substringsBetween (yourString, "<B>", "</B>") с использованием пакета apache commons lang (http://commons.apache.org/lang/) должна выполнить свою работу.

Если вам нужно более общее решение для разных и, возможно, вложенных тегов, вам может потребоваться анализатор, который принимает ввод html и создает из него XML-документ, например NekoHTML, TagSoup, jTidy. Затем вы можете использовать XPath в XML-документе для доступа к содержимому.

Мне нужно получить позиции «<B>» и «</B>» в количестве символов, не включая эти теги. - см. пример в вопросе

pro 12.01.2009 19:38

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