Регулярное выражение Java для нескольких сопоставлений

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

Текст

abcd{123}hello world{456}asd * ~ . , 1243214 aadasd{678}asd aaasddd

Ожидаемый результат

    HEADER -> abcd
    123 -> hello world
    456 -> asd * ~ . , 1243214 aadasd
    678 -> asd aaasddd

Заранее спасибо...

Я пробовал использовать регулярное выражение ниже, но оно не дает правильных результатов

(?:{\d{4}})([\w]+[\S]*[.,]*[\s]+)

немного сбивает с толку: в примере у вас трехзначные числа, но в регулярном выражении вы используете \d{4}, то есть 4-значные?!? И просто пример - не лучшее описание...

user85421 26.06.2024 08:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
79
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Вы можете использовать:

([^\\{\\r\\n]+)?\\{\\s*(\\d+)\\s*\\}([^\\{\\r\\n]+)

Код:


import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Solution {
    public static void main(String[] args) {
        String s = "abcd{123}hello world{456}asd * ~ . , 1243214 aadasd{678}asd aaasddd";

        String p = "([^\\{\\r\\n]+)?\\{\\s*(\\d+)\\s*\\}([^\\{\\r\\n]+)";
        Pattern pattern = Pattern.compile(p);
        Matcher matcher = pattern.matcher(s);

        while (matcher.find()) {
            String header = matcher.group(1);
            String key = matcher.group(2);
            String value = matcher.group(3);

            if (header != null) {
                System.out.println("HEADER -> " + header);
            }
            System.out.println(key + " -> " + value.trim());
        }
    }
}


Принты

HEADER -> abcd
123 -> hello world
456 -> asd * ~ . , 1243214 aadasd
678 -> asd aaasddd

Примечания:

  • ([^{\r\n]+)?: захватить группу 1 для ЗАГОЛОВКА (необязательно ?).
  • ({\d+}): захватите группу 2 по цифрам.
  • ([^{\r\n]+): захватите группу 3 для значений.

Спасибо за быстрый ответ. Это работает отлично, за исключением части ЗАГОЛОВКА. Заголовок также может содержать любые символы. Например. .....01.FTI0350 .FTR811XFT811 {123}привет, мир Пожалуйста, измените свое регулярное выражение, чтобы отразить это

wasanka wickramasinghe 25.06.2024 21:58

@wasankawickramasinghe Попробуйте ([^\{\r\n]+)?\{\s*(\d+)\s*\}([^\{\r\n]+)?

user24714692 25.06.2024 21:59

Если заголовок и все значения должны содержать хотя бы один символ без пробелов и предполагается, что единственные фигурные, которые вы сопоставляете, окружены цифрами:

(?:^\h*+(?!.*}\h*(?:\{|$))([^{}\r\n]+)|\G(?!^))\{(\d+)}([^{}\r\n]+)

Узор соответствует:

  • (?: Группа без захвата
    • ^ Начало строки
    • \h*+ Сопоставьте необязательные ведущие горизонтальные пробельные символы с притяжательным квантором.
    • (?!.*}\h*(?:\{|$)) Утвердить, что справа после } есть не только горизонтальные пробельные символы до следующего { или конца строки.
    • ([^{}\r\n]+) Захватить группу 1, сопоставить 1+ символов, отличных от перечисленных в классе отрицательных символов.
    • | Или
    • \G(?!^) Укажите позицию в конце предыдущего совпадения, а не в начале строки.
  • ) Закройте группу без захвата
  • \{(\d+)} Захватите 1+ цифр между фигурными скобками в группе 2
  • ([^{}\r\n]+) Захватить группу 3, сопоставить 1+ символов, кроме { и }

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

Пример на Java:

String regex = "(?:^\\h*+(?!.*\\}\\h*(?:\\{|$))([^\\{\\}\\r\\n]+)|\\G(?!^))\\{(\\d+)\\}([^\\{\\}\\r\\n]+)";
String string = "abcd{123}hello world{456}asd * ~ . , 1243214 aadasd{678}asd aaasddd";
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher m = pattern.matcher(string);

while (m.find()) {
    if (m.group(1) != null) {
        System.out.printf("HEADER -> %s%n", m.group(1));
    }
    System.out.printf("%s -> %s%n", m.group(2), m.group(3));
}

Выход

HEADER -> abcd
123 -> hello world
456 -> asd * ~ . , 1243214 aadasd
678 -> asd aaasddd

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

([^\\{\\r\\n]+)?\\{\\s*(\\d+)\\s*\\}([^\\{\\r\\n]+)
(?:^\h*+(?!.*}\h*(?:\{|$))([^{}\r\n]+)|\G(?!^))\{(\d+)}([^{}\r\n]+)

Вы показали очень простой формат, очень похожий на CSV, но с чередующимися разделителями:

String line = "abcd{123}hello world{456}asd * ~ . , 1243214 aadasd{678}asd aaasddd";

Есть несколько более простых способов извлечь текст — даже с помощью String.indexOf. Вот несколько предложений, которые вытягивают ваши поля в одну/две строки:

String[] fields = line.split("[\\{\\}]");

Пример доступа:

System.out.println("HEADER -> "+fields[0]);
for (int i = 1; i < fields.length; i+=2) {
    System.out.println(fields[i]+" -> "+fields[i+1]);
}

Альтернатива:

String[] fields = line.split("\\{");

System.out.println("HEADER -> "+fields[0]);
for (int i = 1; i < fields.length; i++) {
    String[] kv = fields[i].split("\\}");
    System.out.println(kv[0]+" -> "+kv[1]);
}

Выход

HEADER -> abcd
123 -> hello world
456 -> asd * ~ . , 1243214 aadasd
678 -> asd aaasddd

Очевидно, что эти предложения могут не касаться пунктуации и проверки случаев, но их легче поддерживать.

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

Переименование строки через матрицу ключ/значение
Руководство по регулярным выражениям: получение определенного значения из текстового файла с помощью powershell/cmd
Регулярное выражение в findstr для поиска URL-адресов в текстовых файлах во всех подпапках
Разделение строки JavaScript с регулярным выражением – совпадение (как заменить регулярное выражение совпадения на функцию разделения)
Регулярное выражение Python, разделение строки с несколькими разделителями
Условное разделение на основе списка столбцов
API chrome.downloads: замена недопустимых символов в имени файла регулярным выражением
Как использовать регулярное выражение pyspark для правильного разрыва данных с каналом, разделенным буквальным каналом внутри?
Поиск всех типов разделителей конца строки в файле
Как получить значения, разделенные запятой, отбрасывая строку перед ней