Regex String Matching - Потенциальная Backsla sh Проблема - PullRequest
0 голосов
/ 02 марта 2020

Я относительно новичок в Python, но прыгаю сразу. Я пытаюсь выяснить, почему моя строка не соответствует должным образом. В основном, я оцениваю текстовый файл, чтобы увидеть, если ключ и путь реестра присутствуют. Это, безусловно, не самый сексуальный код, который вы когда-либо видели, но вот функция, выполняющая проверку регулярных выражений:

     def stigeval (content, regex1, regex2):
        # Now set the registry key path and value
        regex = re.compile(regex1, re.IGNORECASE)

        match = re.search(regex, content)
        if match != None:
            findex = match.start()
            regpathpass = True
            regex = re.compile(regex2, re.IGNORECASE)
            match = re.search(regex, content)
            if match != None:
                findex = match.start()
                regkeypass = True
            else:
                regkeypass = False
        else:
            regpathpass = False
            regkeypass = False

        return(regpathpass, regkeypass)

Вот что я передаю функции:

cregex1 = r'(HKEY_CURRENT_USER\\|HKCU\\|HKCU:\\)\\Software\\Policies\\Microsoft\\Office\\14\.0\\word\\security\\fileblock'
            cregex2 = r'Word97Files\s*=\s*5'

            status = stigeval(content, cregex1, cregex2)

И вот что такое содержание:

01/14/2020 16:28:20
Temp
 HKCU:\\Software\Policies\Microsoft\Office\14.0\word\security\fileblock\Word97Files = 5.

По моим оценкам, регулярное выражение должно соответствовать ключу, указанному выше, но по какой-то причине оно возвращает False. Я уверен, что это потому, что я что-то пропустил. Суть моей проблемы в том, что матч не проводится.

findex = re.search(regex, content).start()
AttributeError: 'NoneType' object has no attribute 'start'

Ответы [ 2 ]

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

Я заметил, что проверка результата match.start() на наличие значения, превышающего 0, не означает, что совпадение было найдено, когда оно действительно было.

>>> cregex1 = r'(HKEY_CURRENT_USER\\|HKCU\\|HKCU:\\)\\Software\\Policies\\Microsoft\\Office\\14\.0\\word\\security\\fileblock'
>>> m = re.search(cregex1, s, re.IGNORECASE)
>>> m.start()
0
>>> m.group(0)
'HKCU:\\\\Software\\Policies\\Microsoft\\Office\\14.0\\word\\security\\fileblock'
>>> 

регулярное выражение применено к

>>> print(s)
HKCU:\\Software\Policies\Microsoft\Office\14.0\word\security\fileblock\Word97Files = 5.
>>> 

Таким образом, в этом фрагменте кода совпадение проходит успешно, но if findex > 0 не является хорошим тестом для определения того, действительно ли оно выполнено или нет, потому что match.start() будет 0, когда совпадение будет найдено.

    findex = re.search(regex, content, re.IGNORECASE).start()
except:
    print('Registry path not found')
    findex = 0
if findex > 0:
    # An index matching the string was found
    regpathpass = True

Эта функция может быть переписана следующим образом:

# Elsewhere in code - maybe top of the file with other "constants".
REG_KEY_HKCU_OFF_FILEBLOCK = re.compile(<expr here>, re.IGNORECASE)
REG_KEY_WORD_FILES         = re.compile(<expr here>, re.IGNORECASE)

def stigeval(content, regex1, regex2):
    # Now set the registry key path and value (??)
    regpathpass = False
    regkeypass  = False
    try:
        regpathpass = regex1.search(content) != None
        if regpathpass:
            regkeypass = regex2.search(content) != None
    except re.error as err:
        print(f'Registry path not found due to error in expression: {err}')
        raise err  # You can do this if you want the error to go 
                   # up the call stack after you've printed the helpful
                   # message.

    return (regpathpass, regkeypass)

Предполагая, что текст, который ищет выражение регулярного выражения, достойны того, чтобы быть константами (частое повторное использование), я помещаю они уже собраны наверху. Они могут быть переданы в качестве параметров при вызове забавы c.

Функция принимает уже скомпилированные регулярные выражения в качестве параметров. Если ключи, переданные этой функции, сильно меняются, и не имеет смысла иметь для них константы. Тогда просто используйте re.search(<regex>...) внутри забавного c - и не тратьте циклы, компилируя их, поскольку они используются только один раз.

Как указал другой ответивший пользователь, блоки try/except должны охватывать как Как можно больше кода, чем одиночных вызовов - , если возможно . Я знаю, что это не всегда так. Но в этом случае вы можете поместить много кода в try/except и значительно упростить вашу функцию.

И еще один пользователь отметил, что except: без захвата указанного исключения c в этом случае опасно потому что, что бы ни случилось, вывод журнала будет «путь не найден». Лучшая стратегия состоит в том, чтобы фиксировать явно плохие выражения и включать их сообщение в выходные данные, или позволить ошибке генерировать стек вызовов, чтобы разработчик знал, что произошла ошибка другого типа, которую он не мог предсказать.

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

Флаги для скомпилированных шаблонов должны быть переданы re.compile.

Ваш код очень труден для чтения и отслеживания, а также слишком сложен для такой простой задачи.

Попробуйте чтобы избежать ненужных блоков try путем перехвата ошибки заранее:

match = re.search(regex, content)
if match != None:
    findex = match.start()

Также избегайте вложения операторов if, обрабатывая вместо этого более простой случай

if findex < 0:
    return
regex = ...

Все это можно было бы предотвратить если только вы напечатали ошибку:

except Exception as e:
    print(e) # cannot process flags argument with a compiled pattern
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...