python输出文本和值_关于python:从包含括号(日志文件)的文本中提取键值对

假设这个字符串:

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

我想要一个像这样的关键值对:

1

2

3

4Key Value

aaa some text here

bbbb3 some other text here

cc more text

或像这样的pandas DataFrame

1

2

3

4aaa | bbbb3 |cc

-------------------------------------------------

some text here | some other text here | more text

next line | ..... | .....

我尝试了一个正则表达式:r'\[(.{6})\]\s(.*?)\s\[',但这不起作用。

试试r'\[([^][]*?)\s*]\s*(.*?)(?=\s*\[|$)',看看这个演示。

stackoverflow.com/questions/26660654/… 先检查一下。

这是进入熊猫DataFrame吗?

@ K.Madden:这不是回答我的问题。 我需要正则表达式来捕获或拆分我的字符串。

@coldspeed:不一定,但我把这个选项打开了

列名是aaa,值是some text here,下一列是bbb,值是some other text here等...

@PatrickArtner:抱歉错字,更新样本

使用re.findall,并将感兴趣的区域提取到列中。然后,您可以根据需要删除空格。

由于您提到您可以将其读入DataFrame,因此您可以将该作业留给pandas。

1

2

3

4

5import re

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

df = (pd.DataFrame(matches, columns=['Key', 'Value'])

.apply(lambda x: x.str.strip()))

1

2

3

4

5df

Key Value

0 aaa some text here

1 bbbb3 some other text here

2 cc more text

或者(Re:编辑),

1

2

3

4

5

6

7df = (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

)

非常感谢,还有正则表达式的解释!是否可以将密钥用作列名?

@JohnDoe Re:编辑,pd.DataFrame(matches, columns=['Key', 'Value']).apply(...).set_index('Key').T

这不是我的意思。我会尝试更好地解释它。现在列是Key和Value,我希望看到第一个捕获组中的column=['aaa', 'bbbb3','cc']和第二个捕获组中的值。关键的价值在于让人感到困惑。我刚刚在这里提到最终得到一个字典,并最终得到一个DataFrame

@JohnDoe是的,想通了。请参阅我的编辑,了解如何以该格式加载它。转置后,列是键。

好,谢谢。我有点困惑,因为我仍然将键值视为索引

如果我正在处理多行,这不起作用。只有最后一个添加到DataFrame

@JohnDoe是的...因为你的问题只与一个字符串有关。考虑打开一个新问题作为后续行动?

试试这个正则表达式,它捕获您在命名组捕获中的键和值。

1\[\s*(?P\w+)+\s*]\s*(?P[^[]*\s*)

说明:

\[ - >由于[具有定义字符集的特殊含义,因此需要对其进行转义并与文字[匹配

\s* - >在不需要键的一部分的预期键之前消耗任何前面的空格

(?P\w+)+ - >形成一个key命名组,捕获一个或多个单词[a-zA-Z0-9_]字符。我使用\w来保持简单,因为OP的字符串只包含字母数字字符,否则应该使用[^]]字符集来捕获方括号内的所有内容作为键。

\s* - >在预期的密钥捕获之后消耗任何后续空间,而不需要密钥的一部分

] - >匹配不需要转义的文字]

\s* - >消耗任何不需要成为值的一部分的前面空格

(?P[^[]*\s*) - >形成一个value命名组,捕获任何字符异常[,此时它将停止捕获并将捕获的值分组到命名组value中。

演示

Python代码,

1

2

3

4

5import re

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

arr = re.findall(r'\[\s*(?P\w+)+\s*]\s*(?P[^[]*\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

19s ="[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

4Key Value

cc more text

aaa some text here

bbbb3 some other text here

Doku格式化:

自定义字符串格式化

字符串格式迷你语言

几乎是1班轮:

1d = {hh[0].strip():hh[1].strip() for hh in (k.split("]") for k in s.split("[") if k)}

您可以通过使用re.split()并输出到字典来最小化所需的正则表达式。例如:

1

2

3

4

5

6

7

8

9

10

11

12import 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'}

在@PatrickArtner的答案中看到更好的基于str.split()的方法(不需要正则表达式)。

使用RegEx,您可以找到key,value对,将它们存储在字典中并打印出来:

1

2

3

4

5

6

7

8

9

10

11

12

13import 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,你可以用你的键/值对做你想做的事:)

你可以使用finditer:

1

2

3

4

5

6

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

最后的结果似乎不正确?

@coldspeed更新了答案!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值