Сопоставление значения ключа регулярного выражения Python

У меня есть файл, который я пытаюсь разобрать, который включает пары ключ-значение. Где ключ начинается с «-», за которым следуют альфа-символы и значение, предшествующее ему, как показано на рисунке ниже.

Когда я анализирую файл с приведенным ниже шаблоном регулярного выражения, я легко могу получить ключи и значения, но когда значения включают несколько слов или данных в кавычках (которые также соответствуют значению ключа), сопоставление моего шаблона не выполняется. Я пробовал несколько итераций сопоставления шаблонов регулярных выражений, но не смог получить желаемый результат. Мне удалось найти шаблон регулярного выражения, соответствующий цитируемому тексту '"(.*?)"', но я не смог использовать оба шаблона одновременно. Любая помощь в получении желаемого результата очень ценится.

Сопоставление значения ключа регулярного выражения Python

Мой код (желаемые результаты только для первой строки):

mystring = '''-desc none -type used -cost med -color blue
-desc none -msg This is a a message -name test
-desc "(-type old -cost high)" -color green'''

mydict = {}
item_num = 0
for line in mystring.splitlines():
    quoted = re.findall('"(.*?)"', line)
    key_value = re.findall('(-\w+\s+)(\S+)', line)
    print(key_value)

### Output ###
[('-desc ', 'none'), ('-type ', 'used'), ('-cost ', 'med'), ('-color ', 'blue')]
[('-desc ', 'none'), ('-msg ', 'This'), ('-name ', 'test')]
[('-desc ', '"(-type'), ('-cost ', 'high)"'), ('-color ', 'green')]

### Desired Output ###
[('-desc ', 'none'), ('-type ', 'used'), ('-cost ', 'med'), ('-color ', 'blue')]
[('-desc ', 'none'), ('-msg ', 'This is a message'), ('-name ', 'test')]
[('-desc ', "(-type old -cost high)"), ('-color ', 'green')]

Проверьте ideone.com/YSw8Cr — работает ли он должным образом?

Wiktor Stribiżew 26.03.2019 16:12

Это удивительное волшебство RegEx! Да сработало именно так, как хотелось. Не могли бы вы дать краткое объяснение используемого здесь шаблона регулярного выражения? Спасибо.

MBasith 26.03.2019 16:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
548
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

(-\w+)\s+("[^"]*"|.*?)(?=$|\s*-\w+\s)

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

Подробности

  • (-\w+) - Группа 1: - и более 1 символа слова
  • \s+ - 1+ пробелы
  • ("[^"]*"|.*?) - Группа 2: ", 0+ символов, кроме ", а затем " или любые 0+ символов, кроме символов разрыва строки, как можно меньше, до первого...
  • (?=$|\s*-\w+\s) - конец строки или 0+ пробелов, -, 1+ словесных символов и пробел.

Регулярный график:

См. демонстрация Python:

import re
mystring = '''-desc none -type used -cost med -color blue
-desc none -msg This is a a message -name test
-desc "(-type old -cost high)" -color green'''

mydict = {}
for line in mystring.splitlines():
    key_value = re.findall(r'(-\w+)\s+("[^"]*"|.*?)(?=$|\s*-\w+\s)', line)
    print(key_value)

Выход:

[('-desc', 'none'), ('-type', 'used'), ('-cost', 'med'), ('-color', 'blue')]
[('-desc', 'none'), ('-msg', 'This is a a message'), ('-name', 'test')]
[('-desc', '"(-type old -cost high)"'), ('-color', 'green')]

Это круто. Спасибо за подробное объяснение и наглядность!

MBasith 26.03.2019 16:23
Ответ принят как подходящий

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

регулярное выражение сырое:

(?<!\S)-(\w+)\s+("[^"]*"|[^\s"-]+(?:\s+[^\s"-]+)*)(?!\S)

необработанный питон:

r"(?<!\S)-(\w+)\s+(\"[^\"]*\"|[^\s\"-]+(?:\s+[^\s\"-]+)*)(?!\S)"

https://regex101.com/r/7bYN1A/1

Ключ = группа 1
Значение = группа 2

 (?<! \S )
 -
 ( \w+ )                       # (1)
 \s+ 
 (                             # (2 start)
      " [^"]* "
   |  [^\s"-]+ 
      (?: \s+ [^\s"-]+ )*
 )                             # (2 end)
 (?! \S )

Ориентир

Regex1:   (?<!\S)-(\w+)\s+("[^"]*"|[^\s"-]+(?:\s+[^\s"-]+)*)(?!\S)
Options:  < none >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   10
Elapsed Time:    1.66 s,   1660.05 ms,   1660048 µs
Matches per sec:   301,196

Сюда не входят значения со специальными символами, такими как "\" и "\&". Например: "-desc n&one -type used -cost med -color bl\ue". Вот это не соответствие "n&one" и "blue". Можно ли обновить его, чтобы включить специальные символы в значения?

MBasith 26.03.2019 17:06

@MBasith - Считаются ли кавычки одним значением: -this "quoted"? или его можно смешивать в значении с другими символами/кавычками: -that here"quoted"there"quoted" ? Или значение может содержать 1,2,3,4, .... разные кавычки? Если вы не знаете, это нормально.

user557597 26.03.2019 17:10

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

MBasith 26.03.2019 17:11

Это прекрасно работает! Могу я спросить, как вы это создали? Было ли это просто благодаря общим знаниям и опыту использования RegEx или у вас есть какой-то инструмент, который может помочь?

MBasith 26.03.2019 17:23

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

user557597 26.03.2019 17:26

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