Извлечение пар ключ-значение из текста, содержащего скобки (файлы журналов) - PullRequest
0 голосов
/ 19 декабря 2018

Допустим, эта строка:

[aaa   ] some text here [bbbb3 ] some other text here [cc    ] more text

Я хотел бы получить ключ и пару значений, например:

Key      Value
aaa      some text here  
bbbb3    some other text here  
cc       more text

или панду DataFrame, как этот

aaa            | bbbb3                |cc
-------------------------------------------------
some text here | some other text here | more text
next line      | .....                | .....

Я попробовал регулярное выражение вроде: r'\[(.{6})\]\s(.*?)\s\[', но это не работает.

Ответы [ 6 ]

0 голосов
/ 19 декабря 2018

С помощью RegEx вы можете найти key,value пар, сохранить их в словаре и распечатать их:

import re

mystr = "[aaa   ] some text here [bbbb3 ] some other text here [cc    ] more text"

a = dict(re.findall(r"\[([A-Za-z0-9_\s]+)\]([A-Za-z0-9_\s]+(?=\[|$))", mystr))

for key, value in a.items():
    print key, value

# OUTPUT: 
# aaa     some text here 
# cc      more text
# bbbb3   some other text here 

RegEx соответствует 2 группам:
Первая группа - все символы, цифры и пробелы внутри заключены в квадратные скобки , а второй - все символы, цифры и пробелы, перед которыми стоят закрытые квадратные скобки и за которыми следуют открытые квадратные скобки или конец строки

Первая группа: \[([A-Za-z0-9_\s]+)\]
Вторая группа: ([A-Za-z0-9_\s]+(?=\[|$))

Обратите внимание, что во второй группе у нас позитивный взгляд : (?=\[|$).Без позитивного взгляда персонаж будет израсходован, и следующая группа не найдет начальную квадратную скобку.

findall возвращает список кортежей: [(key1,value1), (key2,value2), (key3,value3),...].
Список кортежей можетбыть немедленно преобразованным в словарь: dict (my_tuple_list).

Как только вы получите ваш dict, вы можете делать то, что вы хотите с вашими парами ключ / значение:)

0 голосов
/ 19 декабря 2018

Регулярное выражение здесь на самом деле не нужно - простое разбиение строки выполняет свою работу:

s = "[aaa   ] some text here [bbbb3 ] some other text here [cc    ] more text"    

parts = s.split("[")  # parts looks like: ['', 
                      #                    'aaa   ] some text here ',
                      #                    'bbbb3 ] some other text here ', 
                      #                    'cc    ] more text'] 
d = {}
# split parts further
for p in parts:
    if p.strip():
        key,value = p.split("]")            # split each part at ] and strip spaces
        d[key.strip()] = value.strip()      # put into dict

# Output:
form = "{:10} {}"
print( form.format("Key","Value"))

for i in d.items():
      print(form.format(*i))

Вывод:

Key        Value
cc         more text
aaa        some text here
bbbb3      some other text here

Доку для форматирования:


почти как 1-строчный:

d = {hh[0].strip():hh[1].strip() for hh in (k.split("]") for k in s.split("[") if k)}  
0 голосов
/ 19 декабря 2018

Вы можете минимизировать необходимое регулярное выражение, используя re.split() и выводить в словарь.Например:

import re

text = '[aaa   ] some text here [bbbb3 ] some other text here [cc    ] more text'

# split text on "[" or "]" and slice off the first empty list item
items = re.split(r'[\[\]]', text)[1:]

# loop over consecutive pairs in the list to create a dict
d = {items[i].strip(): items[i+1].strip() for i in range(0, len(items) - 1, 2)}

print(d)
# {'aaa': 'some text here', 'bbbb3': 'some other text here', 'cc': 'more text'}
0 голосов
/ 19 декабря 2018

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

import re

s = '[aaa   ] some text here [bbbb3 ] some other text here [cc    ] more text'

pattern = re.compile('\[(\S+?)\s+\]([\s\w]+)')
result = [(match.group(1).strip(), match.group(2).strip()) for match in pattern.finditer(s)]
print(result)

Выход

[('aaa', 'some text here'), ('bbbb3', 'some other text here'), ('cc', 'more text')]
0 голосов
/ 19 декабря 2018

Используйте re.findall и выделите области интереса в столбцы.Затем вы можете убрать пробелы по мере необходимости.

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

import re
matches = re.findall(r'\[(.*?)\](.*?)(?=\[|$)', text)

df = (pd.DataFrame(matches, columns=['Key', 'Value'])
        .apply(lambda x: x.str.strip()))

df
     Key                 Value
0    aaa        some text here
1  bbbb3  some other text here
2     cc             more text

Или (Re: edit),

df = (pd.DataFrame(matches, columns=['Key', 'Value'])
        .apply(lambda x: x.str.strip())
        .set_index('Key')
        .transpose())

Key               aaa                 bbbb3         cc
Value  some text here  some other text here  more text

Шаблон соответствует тексту внутри фигурных скобок, за которым следует текст снаружи до следующей открывающей фигурной скобки.

\[      # Opening square brace 
(.*?)   # First capture group
\]      # Closing brace
(.*?)   # Second capture group
(?=     # Look-ahead 
   \[   # Next brace,
   |    # Or,
   $    # EOL
)
0 голосов
/ 19 декабря 2018

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

\[\s*(?P<key>\w+)+\s*]\s*(?P<value>[^[]*\s*)

Объяснение:

  • \[ -> С[ имеет специальное значение, которое определяет набор символов, следовательно, его необходимо экранировать и он соответствует литералу [
  • \s* -> Использует любой предшествующий пробел перед намеченным ключом, который ненеобходимо ввести часть ключа
  • (?P<key>\w+)+ -> Формирует именованную группу key, содержащую один или несколько слов [a-zA-Z0-9_].Я использовал \w для простоты, поскольку строка OP содержит только буквенно-цифровые символы, в противном случае следует использовать набор символов [^]], чтобы захватить все в квадратных скобках в качестве ключа.
  • \s* -> Расходуетлюбой следующий пробел после предполагаемого захвата ключа, который не нуждается в части ключа
  • ] -> Соответствует литералу ], который не нуждается в экранировании
  • \s*-> Использует любой предыдущий пробел, который не должен быть частью значения
  • (?P<value>[^[]*\s*) -> Формирует именованную группу value, захватывающую любое исключение символа [, в этот момент она прекращает захват игруппирует захваченное значение в именованную группу value.

Демо

Python code,

import re
s = '[aaa   ] some text here [bbbb3 ] some other text here [cc    ] more text'

arr = re.findall(r'\[\s*(?P<key>\w+)+\s*]\s*(?P<value>[^[]*\s*)', s)
print(arr)

Выходы

[('aaa', 'some text here '), ('bbbb3', 'some other text here '), ('cc', 'more text')]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...