Интересно, что ни один из ответов на этой странице не упоминает два крайних случая, надеюсь, никто не возражает, если я их добавлю:
Родовые словари в .NET не являются потокобезопасными, а иногда могут бросать NullReference
или даже (чаще) a KeyNotFoundException
при попытке получить доступ к ключу из двух параллельных потоков. Исключение в этом случае является довольно ошибочным.
Если код NullReferenceException
задан кодом unsafe
, вы можете посмотреть на переменные указателя , и проверьте их на IntPtr.Zero
или что-то в этом роде. Это одно и то же («исключение нулевого указателя»), но в небезопасном коде переменные часто переводятся в типы значений / массивы и т. Д., И вы ударяете головой о стену, задаваясь вопросом, как тип значения может исключение.
(Еще одна причина для небезопасного использования небезопасного кода, если вам это нужно)
Это должно сделать это:
menu_item = '((?:[^'\\]|\\')*)'
Здесь часть (?:[^'\\]|\\')*
соответствует любой последовательности любого символа, кроме '
и \
или литерала \'
. В предыдущем выражении [^'\\]
также допускаются разрывы строк и табуляторы, которые затем необходимо заменить на одно место.
Вы простудились так:
pattern = re.compile(r"menu_item = '(.*?)(?<!\\)'", re.DOTALL)
Он начнет сопоставляться по первой одиночной кавычки, которую он найдет, и заканчивается с первой одиночной цитатой, которой не предшествует обратная косая черта. Он также фиксирует любые новые строки и вкладки, найденные между двумя одинарными кавычками.
Этот протестированный скрипт должен выполнить трюк:
import re
re_sq_long = r"""
# Match single quoted string with escaped stuff.
' # Opening literal quote
( # $1: Capture string contents
[^'\\]* # Zero or more non-', non-backslash
(?: # "unroll-the-loop"!
\\. # Allow escaped anything.
[^'\\]* # Zero or more non-', non-backslash
)* # Finish {(special normal*)*} construct.
) # End $1: String contents.
' # Closing literal quote
"""
re_sq_short = r"'([^'\\]*(?:\\.[^'\\]*)*)'"
data = r'''
menu_item = 'casserole';
menu_item = 'meat
loaf';
menu_item = 'Tony\'s magic pizza';
menu_item = 'hamburger';
menu_item = 'Dave\'s famous pizza';
menu_item = 'Dave\'s lesser-known
gyro';'''
matches = re.findall(re_sq_long, data, re.DOTALL | re.VERBOSE)
menu_items = []
for match in matches:
match = re.sub('\s+', ' ', match) # Clean whitespace
match = re.sub(r'\\', '', match) # remove escapes
menu_items.append(match) # Add to menu list
print (menu_items)
Вот краткая версия регулярного выражения:
'([^'\\]*(?:\\.[^'\\]*)*)'
Это регулярное выражение оптимизировано с использованием метода эффективности Джеффри Фридла «разворачивание-цикл» . (См.: Освоение регулярных выражений (3-е издание) ).
Обратите внимание, что указанное выше регулярное выражение эквивалентно следующему (которое чаще всего встречается, но в большинстве реализаций регулярных выражений NFA оно намного медленнее):
'((?:[^'\\]|\\.)*)'