将半结构化文本列表转换为正式定义

时间:2017-09-23 20:34:45

标签: python regex parsing automated-tests

我试图在Python中实现一个脚本,该脚本会自动将测试序列中定义的事件列表(ERTMS Subset-076-6-3)转换为更正式的定义;为了使用这个新表单在一些日志文件中搜索此事件。

事件以半结构化形式定义,如下例所示:

  • "收到包含数据包255的一个Balise群组消息(NID_BG = BGb)"

  • " DMI符号状态(NID_MESSAGE_JRU = 21; DMI_SYMB_STATUS = LT;位66 = 0& Bit68 = 0& Bit70 = 0& Bit72 = 0& Bit74 = 0& Bit76 = 0>)被记录"

  • "服务制动干预已被记录。"
  • " SA-CONNECT.Confirm已收到"
  • " SA-DATA.Request with Euroradio Message"启动通信会话" (NID_MESSAGE = 155)发送"
  • " SA-DATA.Indication with Euroradio Message" RBC / RIU System Version" (NID_MESSAGE = 32)收到"
  • 驱动程序的验证操作记录在JRU上。

我现在的计划是解析每个事件列表并保存我可以在日志中检查的值(即NID_MESSAGE_JRU = 21 Bit66 = 0 Bit68 = 0 Bit70 = 0 Bit72 = 0 Bit74 = 0 Bit76 = 0)和名称将正确评估条件的函数:

def and():
    return(NID_MESSAGE_JRU==21 && Bit66==0 && Bit68==0 && Bit70==0 && Bit72==0 && Bit74==0 && Bit76==0)

然后程序将解析日志并搜索将返回True的消息,记录匹配以查找其他条件。

现在我正在寻找一种方法来尽可能地自动化这个过程,因为有超过700个测试序列,每个大约有80个事件。

经过一番研究后,我发现使用解析器生成器可以满足我的需求,但我已经陷入了https://tomassetti.me/parsing-in-python/的绝对数量,我无法选择哪一个适合我的问题更好。

我提出的另一个解决方案是使用一些简单的正则表达式来评估我的事件并使用它们生成评估条件,然后在我从日志中加载值之后使用eval()来评估它们:

s = "DMI SYMBOL STATUS (NID_MESSAGE_JRU=21; DMI_SYMB_STATUS=<Bit66=0&Bit68=0&Bit70=0&Bit72=0&Bit74=0&Bit76=0>) is recorded"

s1 = s[s.find("(")+1:s.find(" ")]
s2 = s[s.find("<")+1:s.find(">")]
condition = s1 + s2
condition = re.sub('[=]','==',condition)
condition = re.sub('[;&]', '&&',condition)
condition='NID_MESSAGE_JRU==21&&Bit66==0&&Bit68==0
           &&Bit70==0&&Bit72==0&&Bit74==0&&Bit76==0'

您对哪个解析生成器符合我的需求有什么建议吗?或者我应该继续使用正则表达式?还是我完全走错了路?

1 个答案:

答案 0 :(得分:0)

我想我应该从要解析的字符串的综合列表开始。

我下载了测试数据文件(1009 MB)并将其解压缩(733 .zip文件,1009 MB)。然后我写了

from collections import Counter
import glob
import os
import pyodbc
from zipfile import ZipFile

DATA_DIR      = "~/subset076"        # dir containing test-case .zip files
TEMP_DIR      = "~/subset076/temp"
CONN_STR      = r"DRIVER={{Microsoft Access Driver (*.mdb, *.accdb)}};DBQ={}"
DATA_TABLE    = "TSW_TCStep"
DATA_FIELD    = "ST_DESCRIPTION"

def get_mdbs():
    for fname in glob.glob(os.path.join(DATA_DIR, "*.zip")):
        zf = ZipFile(fname)
        for member in zf.namelist():
            _, ext = os.path.splitext(member)
            if ext.lower() == ".mdb":
                print("Extracting", member)
                zf.extract(member, path = TEMP_DIR)

def get_test_strings():
    test_strings = Counter()
    sql = "SELECT {} FROM {}".format(DATA_FIELD, DATA_TABLE)
    for fname in glob.glob(os.path.join(TEMP_DIR, "*.mdb")):
        print("Working on", fname)
        with pyodbc.connect(CONN_STR.format(fname)) as conn:
            cursor = conn.cursor()
            cursor.execute(sql)
            test_strings.update(row[0] for row in cursor)
    return test_strings

get_mdbs()
ts = get_test_strings()

解压缩所有.mdb文件(733个文件,718 MB)并获取所有测试序列事件字符串。我最终得到了4495个独特的字符串,总共73320个字符串。排序后,得到https://pastebin.com/reSGn8JE(约400 kB)。

我明天继续实际解析它......