Как разобрать строку с помощью регулярного выражения

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

String text = test.get(i).toString()
// text looks like this in string form:
// EnumOption[enumId=test,id=machine]

String checker = text.replace("[","").replace("]","").split(",")[1].split(" = ")[1];

// checker becomes machine

Моя цель — разобрать эту text строку и просто вернуться обратно machine. Что я и сделал в приведенном выше коде.

Но это выглядит некрасиво. Мне было интересно, какое регулярное выражение можно использовать здесь, чтобы сделать это немного лучше? Или, может быть, другое предложение?

Для уточнения: хотите ли вы получить строку, написанную после id=, независимо от следующей строки?

BeWu 14.12.2020 18:26
String checker = text.replaceFirst("EnumOption\\[enumId=test,id=(.*)\\]", "$1"); а нет ли более простого варианта вроде test.get(i).getId()?
Holger 14.12.2020 18:31

Что такое test? Как сказал Хольгер, нельзя ли получить идентификатор объекта напрямую, минуя обходной путь через toString()?

Konrad Rudolph 14.12.2020 18:40

@Holger, я на 100% согласен с тобой, но в Eclipse, когда я пытался это сделать. .getId() не вариант. Я мало знаю о java. Я просто предположил, что если Eclipse не показывает его доступным, то он недоступен.

adbarads 14.12.2020 20:30

test — это customTypedList, и я перебираю его, перебирая каждый элемент. и каждый элемент является enumOption

adbarads 14.12.2020 20:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
5
197
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

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

PS: я думаю, что ваше решение на самом деле вполне читабельно.

Вот еще одна версия без регулярных выражений:

String text = "EnumOption[enumId=test,id=machine]";
text = text.substring(text.lastIndexOf('=') + 1);
text = text.substring(0, text.length() - 1);

Не делаю вам одолжения, но отрицательный голос причиняет боль, так что вот:

String input = "EnumOption[enumId=test,id=machine]";
Matcher matcher = Pattern.compile("EnumOption\\[enumId=(.+),id=(.+)\\]").matcher(input);
if (!matcher.matches()) {
  throw new RuntimeException("unexpected input: " + input);
}

System.out.println("enumId: " + matcher.group(1));
System.out.println("id: " + matcher.group(2));

Когда вы говорите о производительности, мне интересно, почему вы без необходимости выполняете две substring операции вместо одной text.substring(text.lastIndexOf('=') + 1, text.length() - 1)

Holger 14.12.2020 18:33

Я не имел в виду, что моя версия более производительна. Я обычно оптимизирую для удобочитаемости и скорости реализации. Это был скорее общий комментарий.

Reto Höhener 14.12.2020 18:35

Итак, вы думаете, что выполнение двух операций substring вместо одной делает код более читабельным?

Holger 14.12.2020 18:37

Не на самом деле нет. Примерно так же просто, как собственное решение ОП. Читаемый, простой для понимания и пошаговый с отладчиком.

Reto Höhener 14.12.2020 18:39
int start = text.lastIndexOf("id = "); int end = text.length() - 1; text = text.substring(start, end); Почему это не более читабельно, чем две подстроки?
Olivier Grégoire 14.12.2020 22:37

@OlivierGrégoire Возможно, это даже более читабельно. Я чувствую себя очень неправильно понятым. Я пытался сказать, что любое решение, не связанное с регулярными выражениями, часто быстрее реализуется, его легче понять и поддерживать.

Reto Höhener 15.12.2020 09:05
Ответ принят как подходящий

Используйте поиск назад регулярного выражения:

(?<=\bid=)[^],]*

См. Regex101.

(?<=     )            // Start matching only after what matches inside
    \bid=             // Match "\bid = " (= word boundary then "id = "),
          [^],]*      // Match and keep the longest sequence without any ']' or ','

В Java используйте это так:

import java.util.regex.*;

class Main {
  public static void main(String[] args) {
    Pattern pattern = Pattern.compile("(?<=\\bid=)[^],]*");
    Matcher matcher = pattern.matcher("EnumOption[enumId=test,id=machine]");
    if (matcher.find()) {
      System.out.println(matcher.group(0));
    }
  }
}

Это приводит к

machine

Предполагая, что вы используете Polarion ALM API, вы должны использовать метод EnumOptiongetId вместо депарсинга и повторного анализа значения через строку:

String id = test.get(i).getId();

Использование функций замены и разделения не учитывает структуру данных.

Если вы хотите использовать регулярное выражение, вы можете просто использовать группу захвата без каких-либо обходов, где enum может быть любым значением, кроме ] и запятой, а id может быть любым значением, кроме ].

Значение id будет в группе захвата 1.

\bEnumOption\[enumId=[^=,\]]+,id=([^\]]+)\]

Объяснение

  • \bEnumOption Соответствие EnumOption, которому предшествует граница слова
  • \[enumId= Матч [enumId=
  • [^=,\]]+, Совпадение 1+ раз с любым символом, кроме =, и ]
  • id= Совпадение буквально
  • ( Группа захвата 1
    • [^\]]+ Совпадение 1+ раз с любым символом, кроме ]
  • )\]

Демонстрация регулярных выражений | Демонстрация Java

Pattern pattern = Pattern.compile("\\bEnumOption\\[enumId=[^=,\\]]+,id=([^\\]]+)\\]");
Matcher matcher = pattern.matcher("EnumOption[enumId=test,id=machine]");

if (matcher.find()) {
    System.out.println(matcher.group(1));
}

Выход

machine

Если может быть больше значений, разделенных запятыми, вы также можете сопоставлять id только с использованием отрицательных классов символов [^][]* до и после сопоставления id, чтобы оставаться в пределах квадратных скобок.

\bEnumOption\[[^][]*\bid=([^,\]]+)[^][]*\]

В Яве

String regex = "\\bEnumOption\\[[^][]*\\bid=([^,\\]]+)[^][]*\\]";

Демонстрация регулярных выражений

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