Соответствие значения ключа Python Regex - PullRequest
2 голосов
/ 26 марта 2019

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

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

Keys and Values

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

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')]

Ответы [ 2 ]

0 голосов
/ 26 марта 2019

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

regex raw:

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

Python Raw :

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 )

Benchmark

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
0 голосов
/ 26 марта 2019

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

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

См. Демоверсию regex .

Подробности

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

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

enter image description here

См. Демонстрационную версию 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')]
...