Вложенное регулярное выражение с несколькими шаблонами, используя Python re - PullRequest
2 голосов
/ 04 марта 2020

Каков эквивалентный способ написания этой программы sed в Python с использованием библиотеки re? Этот шаблон sed завершает поиск за один проход и его эффективность. Я пытаюсь извлечь номер модели процессора. Пожалуйста, смотрите мою 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

Sed:

/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 (не работает):

Мой код ищет каждое выражение и не ' t следовать любым правилам вложенности, что неэффективно. Ищите лучший способ написать это.

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())

Ответы [ 2 ]

1 голос
/ 05 марта 2020

Принимая во внимание полезный совет по https://blog.codinghorror.com/regular-expressions-now-you-have-two-problems/, не основывайте свой код python на сценарии sed, начните с чего-то приятного и простого, например, этого сценария awk:

$ cat tst.awk
/^vendor_id/ {
    vendor = $NF
}
/^model name/ {
    model = "Unknown"
    if ( vendor == "GenuineIntel" ) {
        model = $7
    }
    else if ( vendor == "AuthenticAMD" ) {
        model = $5 " " $6
    }
    print model
}

, который, я уверен, вы можете легко реализовать и в python. Вот пример того, как он работает с вашими 2 блоками ввода образца в одном файле:

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

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

$ awk -f tst.awk file
E5-2660
EPYC 7601
1 голос
/ 05 марта 2020

Имея полнофункциональный язык, такой как 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)

Об эффективности - до тех пор, пока у вас нет миллионов строк для анализа, вы не не нужно об этом беспокоиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...