У меня есть файл, который структурирован следующим образом:
Line
foo Änderbar: PM baz
Line
Line
foo Änderbar: OM baz
Line
Line
foo Änderbar: ++ baz
Line
Line
foo Änderbar: -- baz
Line
Таким образом, файл состоит из «блоков», разделенных новой строкой (я преобразовал файл в конец строки Unix). Каждый блок может иметь произвольное количество строк. Каждая строка блока содержит как минимум один символ, который не является новой строкой и заканчивается символом новой строки. Строки, разделяющие блоки, состоят ровно из одного символа новой строки.
В каждом блоке есть ровно одна строка в следующем формате:
- хотя бы один символ, который не является новой строкойсопровождаемый
- литеральной строкой
'Änderbar: '
, сопровождаемый - точно одной из буквенных строк
'++'
, '--'
, 'OM'
, 'PM'
, сопровождаемый - хотя бы один символ, который не является символом новой строки, за которым следует
- символ новой строки, заканчивающийся строкой
В той же строке всегда есть хотя бы еще одна непустая строкаблок выше этой специальной строки и еще одна непустая строка ниже этой специальной строки.
Мне нужен эффективный метод для поиска (и, следовательно, выбора) всех блоков, где литерал после Änderbar:
равен --
(найти/ выберите один блок за другим, каждый после повторного нажатия Find Next
, то есть не выбирая все эти блоки одновременно).
Обычно я получаю удовольствие от решения таких проблем с помощью Notepad ++. Тем не менее, в этом случае кажется, что я становлюсь все более и более глупым с возрастом, или что есть ошибка в обработчике регулярных выражений Notepad ++.
Notepad ++ использует BOOST (и поддерживает выражения PCRE через BOOST),Поскольку это широко используется, я считаю эту проблему достаточно важной, чтобы разместить ее здесь, на тот случай, если BOOST действительно является причиной неправильного поведения.
Сказав это: я загрузил этот файл в Notepad ++, запустилв диалоговом окне «Поиск и замена» отметили . matches newline
, отметили Regular Expression
и ввели следующее регулярное выражение в текстовое поле Find What:
:
\n([^\n]+\n)+[^\n]+(Änderbar\:\ --[^\n]+\n)([^\n]+\n)+
Я был очень удивлен, что это заставило Notepad ++ вести себя странно: когда курсорбыл помещен в пустую строку непосредственно перед блоком с Änderbar: --
, ударив Find Next
нашел / выбрал этот блок, как и ожидалось. Но когда курсор был в другом месте, нажатие Find Next
заставило Notepad ++ найти / выбрать весь остальной файл , то есть все блоки ниже позиции курсора.
Затем я проверил,он обнаружил бы блоки, имеющие ++
после Änderbar:
, т.е. я изменил свое регулярное выражение на
\n([^\n]+\n)+[^\n]+(Änderbar\:\ \+\+[^\n]+\n)([^\n]+\n)+
Угадайте, что: это работало надежно в каждой ситуации. То же самое верно для последних обоих:
\n([^\n]+\n)+[^\n]+(Änderbar\:\ PM[^\n]+\n)([^\n]+\n)+
\n([^\n]+\n)+[^\n]+(Änderbar\:\ OM[^\n]+\n)([^\n]+\n)+
Так что Notepad ++ / PCRE, похоже, имеет проблему с правильной интерпретацией -
при определенных обстоятельствах, или у меня есть небольшая ошибка в моем регулярном выражении, которая толькосрабатывает, когда я ищу --
(вместо ++
, OM
или PM
) в соответствующем месте.
Обратите внимание, что я уже пытался опустить \
вперед символом пробела (что на самом деле могло только усугубить ситуацию, но я попробовал на всякий случай) и что я также попытался использовать \-\-
вместо --
(хотя последнее должно быть в порядке). Это никак не изменило (неправильное) поведение.
Так в чем здесь проблема? Есть ли ошибка в моем регулярном выражении или в Notepad ++?
ОБНОВЛЕНИЕ
Я удалил нужный файл и загрузил его в https://pastebin.com/w62E57U5. Чтобы воспроизвести проблему, выполните следующие действия:
Загрузите файл по ссылке выше и сохраните его где-нибудь на жестком диске (не копируйте текст непосредственно в Notepad ++).
Загрузить файл в Блокнот ++. Курсор теперь находится в самой верхней строке, и ничего не выделено.
Это важно: Нажмите Правка -> Преобразование EOL -> Unix (LF).
Убедитесь, что курсор все еще находится в самой верхней строке (которая пуста) и что ничего не выбрано.
Откройте диалоговое окно «Найти», выберите настройки и введите строку поиска, как описано выше.
Нажмите «Найти далее».
Обратите внимание, что теперь полный текст найден / выделен.
Оставив окно поиска открытым, удалите третью строку файла (там написано "Funktionspaket (e): ML"). ). Не просто очистите эту строку, но действительно удалите ее, чтобы между строкой до и после нее не осталось пустой строки.
Опять же, поместите курсор в самую верхнюю строку (котораявсе еще пусто) и убедитесь, что ничего не выбрано.
Нажмите «Найти далее».
Обратите внимание, что регулярное выражение теперь работает как положено.
Очевидно, кто-то пытается одурачить меня, верно?