Extract key-value pairs from text containing brackets (log files)
假设这个字符串:
1 | [aaa ] some text here [bbbb3 ] some other text here [cc ] more text |
我想要一个像这样的关键值对:
1 2 3 4 | Key Value aaa some text here bbbb3 some other text here cc more text |
或像这样的pandas DataFrame
1 2 3 4 | aaa | bbbb3 |cc ------------------------------------------------- some text here | some other text here | more text next line | ..... | ..... |
我尝试了一个正则表达式:
使用
由于您提到您可以将其读入DataFrame,因此您可以将该作业留给pandas。
1 2 3 4 5 | import re matches = re.findall(r'\[(.*?)\](.*?)(?=\[|$)', text) df = (pd.DataFrame(matches, columns=['Key', 'Value']) .apply(lambda x: x.str.strip())) |
1 2 3 4 5 | df Key Value 0 aaa some text here 1 bbbb3 some other text here 2 cc more text |
或者(Re:编辑),
1 2 3 4 5 6 7 | 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 |
该模式匹配大括号内的文本,然后是文本外部到下一个左大括号。
1 2 3 4 5 6 7 8 9 | \[ # Opening square brace (.*?) # First capture group \] # Closing brace (.*?) # Second capture group (?= # Look-ahead \[ # Next brace, | # Or, $ # EOL ) |
试试这个正则表达式,它捕获您在命名组捕获中的键和值。
1 | \[\s*(?P<key>\w+)+\s*]\s*(?P<value>[^[]*\s*) |
说明:
-
\[ - >由于[ 具有定义字符集的特殊含义,因此需要对其进行转义并与文字[ 匹配 -
\s* - >在不需要键的一部分的预期键之前消耗任何前面的空格 -
(?P - >形成一个\w+)+ key 命名组,捕获一个或多个单词[a-zA-Z0-9_]字符。我使用\w 来保持简单,因为OP的字符串只包含字母数字字符,否则应该使用[^]] 字符集来捕获方括号内的所有内容作为键。 -
\s* - >在预期的密钥捕获之后消耗任何后续空间,而不需要密钥的一部分 -
] - >匹配不需要转义的文字] -
\s* - >消耗任何不需要成为值的一部分的前面空格 -
(?P - >形成一个[^[]*\s*) value 命名组,捕获任何字符异常[ ,此时它将停止捕获并将捕获的值分组到命名组value 中。
演示
Python代码,
1 2 3 4 5 | 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) |
输出,
1 | [('aaa', 'some text here '), ('bbbb3', 'some other text here '), ('cc', 'more text')] |
这里并不真正需要正则表达式 - 简单的字符串拆分可以完成工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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)) |
输出:
1 2 3 4 | Key Value cc more text aaa some text here bbbb3 some other text here |
Doku格式化:
- 自定义字符串格式化
- 字符串格式迷你语言
几乎是1班轮:
1 | d = {hh[0].strip():hh[1].strip() for hh in (k.split("]") for k in s.split("[") if k)} |
您可以通过使用
1 2 3 4 5 6 7 8 9 10 11 12 | 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'} |
使用RegEx,您可以找到
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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组:
第一组是用方括号括起来的所有字符,数字和空格,第二组是所有字符,数字和空格,前面是一个封闭的方括号,后面是一个空方括号或行的末尾
第一组:
第二组:
请注意,在第二组中,我们有一个积极的前瞻:
然后findall返回一个元组列表:
元组列表可以立即转换为字典:dict(my_tuple_list)。
一旦你有了dict,你可以用你的键/值对做你想做的事:)
你可以使用finditer:
1 2 3 4 5 6 7 | 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) |
产量
1 | [('aaa', 'some text here'), ('bbbb3', 'some other text here'), ('cc', 'more text')] |