import re # 导入正则表达式模块
# 更改这个元组内容的顺序即可给改变数据对应的顺序,不用改变封装好的函数
Position = ('Direction', 'Distance', 'DirChng', 'DistChng', 'BodyDir', 'HeadDir') # 使用tuple元组不可修改其内容
def outPutInfo(info):
"""
格式化输出解析出来的数据包
:param info: 解析出来的信息包
:return: 无
"""
hear = info['hear'] # 获取听到的数据包
see = info['see'] # 获取看到的数据包
if hear != '':
print("在 {} 周期 hear 从 {} 方向 听到了 {};".format(hear['time'], hear['Sender'], hear['Message']))
pass
if see != '':
print('在 {} 周期 see'.format(see['time']), end=' ')
see = see['obj_list'] # 去掉第一个时间
for item in see:
for key, value in item.items(): # 获取信息
if 'ObjName'.__eq__(key):
print(item[key], end=' ')
elif 'Direction'.__eq__(key):
print("距离我的 Direction 是 {},".format(item[key]), end=' ')
elif 'Distance'.__eq__(key):
print("Distance 是 {},".format(item[key]), end=' ')
elif 'DirChng'.__eq__(key):
print("DirChng 是 {},".format(item[key]), end=' ')
elif 'DistChng'.__eq__(key):
print("DistChng 是 {},".format(item[key]), end=' ')
elif 'BodyDir'.__eq__(key):
print("它的 BodyDir 是 {}".format(item[key]), end=' ')
elif 'HeadDir'.__eq__(key):
print("和 HeadDir 是 {}".format(item[key]), end=';')
pass
print() # 添加一个换行,使得输出更直观
pass
pass
def decode(msg):
"""
对消息进行解析
:param msg: 要解析的字符串
:return: 解析完的数据包
"""
package = packMsg(msg) # 首先将整个消息分块打包,分出大的数据包
worked_msg = {'hear': '', 'see': ''}
if not package: # 如果分离出的数据包是空的,说明传入的字符串没有数据
print('未检测到数据包!')
else:
for item in package: # 循环最外层的大数据包
msg_type = re.findall('[(](.*?) ',item)[0] # 拿到数据包的类型
if 'see'.__eq__(msg_type): # 如果数据包是see类型
see = {'type': 'see', 'time': re.findall(r'\d+', item)[0]}
obj_info = packMsg(item, 1) # 跳过第一个左括号
# print(obj_info)
obj_list = [] # 创建一个对象列表,用于存储对象
for obj in obj_info: # 循环所有对象信息
tmp = dict()
tmp['ObjName'] = re.findall('[(]{2}(.*?)[)]', obj)[0] # 拿到名字信息
# print(tmp)
position_info = re.findall('[)](.*?)[)]',obj)[0] # 拿到位置信息
position_info = position_info.split(' ') # 将位置信息分割出来
# print(position_info)
i = 0
for pos in position_info: # 循环每个对象的位置信息
if pos != '':
tmp[Position[i]] = pos
# print(pos)
i += 1
pass
pass
obj_list.append(tmp) # 将对象加入到对象列表中
pass
see['obj_list'] = obj_list
# print(see)
worked_msg['see'] = see
pass # 处理完看到的信息
elif 'hear'.__eq__(msg_type):
item = item[1:len(item)-1] # 去掉最外面的左右括号
hear = {'type': 'hear', 'time': item.split(' ')[1], 'Sender': item.split(' ')[2]
, 'Message': item.split(' ')[3]}
worked_msg['hear'] = hear
pass # 处理完听到的信息
pass # 最外层循环的大数据包,
pass # 数据处理完成
return worked_msg
def packMsg(msg,start=0):
"""
匹配一对括号里面所有内容惊醒打包
:param msg: 要打包的信息
:param start: 检查的起始位置,默认是0从头来开始
:return: 打包完成的信息包组成的列表,若没有消息包就返回空列表
"""
num = 0
index = 0
tmp = []
msg = msg[start:]
for s in msg:
if s == '(':
num += 1
if num == 1:
start = index
elif s == ')':
num -= 1
if num == 0:
tmp.append(msg[start:index+1])
start = index+1
index += 1
return tmp
if __name__ == '__main__':
msg = input("请输入你需要解析的字符串信息:")
# msg = '(hear 1022 -30 passto(23,24))(see 1022 ((ball) -20 20 1 -2) ((player hfut1 2) 45 23 0.5 1 22 40 ) ((goal r) 12 20) ((Line r) -30))'
# msg = '(see 2022 ((player hfut2 8) 40 23 1 6 21 33 ) ((goal r) 15 30) ((f r t 20)5 24 ))(hear 2022 -10 “passball”)'
# msg = '(hear 2022 -10 “passball”)'
print('\033[1;31m程序是按照作业PPT参数的顺序进行解包和输出的!\033[0m')
worked_info = decode(msg) # 对接受的数据进行解析
outPutInfo(worked_info) # 格式化输出
# print(worked_info) # 可以查看解析后的数据包
"""
样例输入:
(hear 1022 -30 passto(23,24))(see 1022 ((ball) -20 20 1 -2) ((player hfut1 2) 45 23 0.5 1 22 40 ) ((goal r) 12 20) ((Line r) -30))
样例输出:
在 1022 周期 hear 从 -30 方向 听到了 passto(23,24);
在 1022 周期 see ball 距离我的 Distance 是 -20, Direction 是 20, DirChng 是 1, DistChng 是 -2,
player hfut1 2 距离我的 Distance 是 45, Direction 是 23, DirChng 是 0.5, DistChng 是 1, 它的 BodyDir 是 22 和 HeadDir 是 40;
goal r 距离我的 Distance 是 12, Direction 是 20,
Line r 距离我的 Distance 是 -30,
"""