首页 > 解决方案 > 使用 Python re 的多模式嵌套正则表达式

问题描述

使用 re 库在 Python 中编写这个 sed 程序的等效方法是什么?这种 sed 模式一次性完成搜索,而且效率很高。我正在尝试提取 cpu 的型号。请在底部查看我的 Python 代码尝试。

样本输入:

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz
stepping        : 6

输出:

E5-2660

样本输入 2:

processor       : 127
vendor_id       : AuthenticAMD
cpu family      : 23
model           : 1
model name      : AMD EPYC 7601 32-Core Processor
stepping        : 2

输出:

EPYC 7601

赛德:

/AuthenticAMD/{
    s/.*/AMD/p
}
/GenuineIntel/ {
    n
    n
    n
    /Celeron/ {            
        s/.*\([egptEGPT][1-9][0-9][0-9][0-9][a-zA-Z][a-zA-Z]\).*/\1/p 
        s/.*\([egptEGPT][1-9][0-9][0-9][0-9][a-zA-Z]\).*/\1/p 
        s/.*\([egptEGPT][1-9][0-9][0-9][0-9]\).*/\1/p
        q
    }
    /Xeon/ {
        s/.*[eE][3579]-\([1-9][1-9][1-9][1-9]\).*/\1/p
        s/.*\([eElL]C[1-9][0-9][0-9][0-9]\).*/\1/p
        s/.*\([35][0-9][0-9][0-9]\).*/\1/p
        q
    }
}

在 Python 中尝试(不工作):

我的代码搜索每个表达式并且不遵循任何嵌套规则,效率不高。寻找更好的方法来写这个。

string = """processor       : 0
            vendor_id       : GenuineIntel
            cpu family      : 6
            model           : 45
            model name      : Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz
            stepping        : 6"""

pattern = r'''GenuineIntel.*
                (?=Celeron
                    .*([egptEGPT][1-9][0-9][0-9][0-9][a-zA-Z][a-zA-Z]).*
                    .*([egptEGPT][1-9][0-9][0-9][0-9][a-zA-Z]).*
                    .*([egptEGPT][1-9][0-9][0-9][0-9]).*)|
                (?=Xeon
                    .*([eE][3579]-[1-9][0-9][0-9][0-9]).*)'''

print(re.search(pattern, string, re.MULTILINE|re.DOTALL|re.VERBOSE).groups())

标签: pythonregexsed

解决方案


拥有像 Python 这样功能齐全的语言和结构良好的数据,我不会尝试使用正则表达式解析所有内容。相反,我只是写了一个代码来完成这项工作,只在最后使用正则表达式。通过这种方式,我可以使用非常简单的正则表达式获得简短易读的代码,而不是庞大的正则表达式。

data = {}
for line in string.split("\n"):
    left, right = line.split(":")
    data[left.strip()] = right.strip()

if data["vendor_id"] == "GenuineIntel":
    model = data["model name"]
    if "Xeon" in model:
        code = re.search(r"\bE\d-\d{4}\b", model, re.I).group(0)
    elif "Celeron" in model:
        code = re.search(r"\b[EGPT]\d{4}[a-z]{0,2}\b", model, re.I).group(0)

print(code)

关于效率——只要你没有数以百万计的字符串要解析,你就不必担心它。


推荐阅读