多字符串格式的解析挑战

2024-05-15 14:02:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图解析设备日志,但格式不一致

示例:

Roam candidate# 9 F4:CF:E2:5E:73:3F on channel 161  RSSI: -70

Roam candidate#10 F4:CF:E2:62:02:2F on channel 11  RSSI: -70

我想提取Mac地址、通道和RSSI值
不幸的是,在候选值变为10或更高之后,空格被省略。你知道吗

我试着把它标记出来,但我几乎不了解这个过程

def clean(string):
    result = ""
    for i,char in enumerate(line):
        if char == " ":
            if string[i+1].isdigit() or string[i+1] == " ":
                continue
        result += char
    return result

def tokenize(string):
    result = []
    previous = 0
    for i,char in enumerate(string):
        if char == " ":
            result.append(string[previous:i])
            previous = i+1
        elif i == len(string)-1:
            result.append(string[previous:i+1])
    return result

我只得到最后一列(RSSI)作为输出


Tags: forstringifondefchannelresultcandidate
3条回答

对于regex,它的工作方式如下:

import re
s1="Roam candidate# 9 F4:CF:E2:5E:73:3F on channel 161 RSSI: -70"
s2="Roam candidate#10 F4:CF:E2:62:02:2F on channel 11 RSSI: -70"

patt= re.compile('(?P<mac>[0-9A-F]{2}(:[0-9A-F]{2}){5}).*?channel (?P<channel>[0-9]*).*?RSSI:\s*(?P<rssi>-?[0-9]*)', re.I)

matcher= patt.search(s1)

print(matcher.group('mac'))
print(matcher.group('channel'))
print(matcher.group('rssi'))

这将返回:

F4:CF:E2:5E:73:3F
161
-70

对于第二行:

F4:CF:E2:62:02:2F
11
-70

简单点的可能更好

r"(?i)([a-f0-9]{2}(?::[a-f0-9]{2})+)\s.*?\s(\d+)\s.*?\s(-?\d+)"

https://regex101.com/r/smcjY5/1

扩展

 (?i)
 (                             # (1 start)
      [a-f0-9]{2} 
      (?: : [a-f0-9]{2} )+
 )                             # (1 end)
 \s .*? \s 
 ( \d+ )                       # (2)
 \s .*? \s 
 ( -? \d+ )                    # (3)

如果要使用模式,可以使用3个捕获组,1个用于mac地址,1个用于通道,1个用于RSSI值:

Roam candidate# ?\d+ ((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]){2}) on channel (\d+) +RSSI: (-?\d+)

在较小的部分:

  • Roam candidate# ?\d+匹配漫游候选#,可选空格和1+数字
  • ((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]){2})捕获组1,匹配mac地址
  • on channel (\d+) +在通道上匹配,空格后在组2 1+中捕获
  • RSSI: (-?\d+)匹配RSSI:,空格并在第3组中捕获一个可选的-和1+数字

Regex demo| Python demo

例如

import re

strings = ["Roam candidate# 9 F4:CF:E2:5E:73:3F on channel 161  RSSI: -70", "Roam candidate#10 F4:CF:E2:62:02:2F on channel 11  RSSI: -70"]
regex = r"Roam candidate# ?\d+ ((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]){2}) on channel (\d+) +RSSI: (-?\d+)"
for s in strings:
    print(re.findall(regex, s, re.M))

结果

[('F4:CF:E2:5E:73:3F', '161', '-70')]

[('F4:CF:E2:62:02:2F', '11', '-70')]

相关问题 更多 >