Регулярное выражение с использованием отрицательного просмотра назад не работает в Notepad ++

У меня есть исходный файл с буквально сотнями вхождений строк flecha.jpg и flecha1.jpg, но мне нужно найти вхождения любого другого .jpg изображения (т.е. casa.jpg, moto.jpg и т. Д.)

Я пробовал использовать регулярное выражение с отрицательной ретроспективой, например:

(?<!flecha|flecha1).jpg

но это не работает! Notepad ++ просто говорит, что это недопустимое регулярное выражение.

Я пробовал регулярное выражение в другом месте, и оно работает, вот пример, поэтому я предполагаю, что это проблема с обработкой NPP регулярных выражений или с синтаксисом lookbehind / lookaheads.

Итак, как я могу добиться того же результата регулярного выражения в NPP?

Если полезно, я использую Notepad ++ версии 6.3 Unicode.

В качестве дополнения, если вы так любезны, каков будет синтаксис для достижения того же самого, но с дополнительными числами (в данном случае только «1») в качестве суффикса моей строки? (даже если на АЭС не работает, просто чтобы знать) ...

Я попробовал (?<!flecha[1]?).jpg, но это не сработало. Он должен работать так же, как и другое регулярное выражение, см. Здесь (RegExr)


person DiegoDD    schedule 24.06.2013    source источник


Ответы (3)


В Notepad ++, похоже, не реализована функция просмотра назад с переменной длиной (это происходит с некоторыми инструментами). Обходной путь - использовать более одного просмотра назад фиксированной длины:

(?<!flecha)(?<!flecha1)\.jpg

Как вы можете проверить, совпадения совпадают. Но это работает с npp.

Обратите внимание, что я экранировал ., поскольку вы пытаетесь сопоставить расширения, вам нужен буквальный .. Как и у вас, это был подстановочный знак - мог быть любой символ.

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

person acdcjunior    schedule 25.06.2013
comment
На более яркой ноте, вы можете использовать [0-9], \d или другие подобные, если длина каждого просмотра остается фиксированной: (?<!flecha)(?<!flecha[1-3])\.jpg - person acdcjunior; 25.06.2013
comment
Копнул еще немного и получил подтверждение того, о чем мы думали: Notepad ++ использует Boost как реализацию регулярного выражения, а Boost Regex поддерживает только просмотр назад фиксированной длины. - person acdcjunior; 25.06.2013
comment
Отлично! Небольшое сомнение относительно вашего ответа; ограничение отсутствия ретроспективного анализа переменной длины применяется в этом случае только к Npp? или для Regex и других инструментов? то есть в других инструментах я мог бы использовать ретроспективы переменной длины? Или это ограничение RegEx и больше нигде не сработает? - person DiegoDD; 26.06.2013
comment
Это не ограничение для регулярных выражений в целом. Я имею в виду, что у инструмента / языка могут быть ретроспективы переменной длины, это просто зависит от них. Для АЭС сейчас это ограничение. Видите ли, в npp до 6.3 вообще не было ретроспективы. Для них это в новинку. У других инструментов своя история. Perl версии 5 и ниже также не имел функции просмотра назад переменной длины, в более поздних версиях она есть. JavaScript вообще не имеет ретроспективного анализа, в то время как Java имеет ретроспективный анализ переменной длины, где максимальная длина может быть известна заранее ((?<=[a|abc]) было бы хорошо, но (?<=a|.*) - нет). - person acdcjunior; 26.06.2013
comment
Кроме того, поскольку вы хотите сопоставить только расширение, ваш единственный ресурс / возможность - поиск назад. Если вы могли бы сопоставить другие части (и, возможно, использовать replace с группой, чтобы вернуть их), есть возможность более простых регулярных выражений. - person acdcjunior; 26.06.2013
comment
Спасибо еще раз. Я думал, что все или, по крайней мере, большинство инструментов должны иметь одни и те же правила для реализации регулярных выражений, но, как я вижу, это не так, и у них могут быть разные ограничения. Это позор. Он должен быть стандартным, чтобы регулярное выражение могло работать где угодно. Спасибо за обстоятельный ответ / комментарии! - person DiegoDD; 26.06.2013
comment
@acdcjunior, возможно, вы захотите добавить этот бит об использовании Boost в свой ответ. - person SQB; 06.09.2018

Решение проблемы ограничения переменной длины с отрицательным просмотром назад в Notepad ++

Ниже приведены несколько стратегий для обхода этого ограничения в Notepad ++ (или в любом механизме регулярных выражений с таким же ограничением).

Определение проблемы

Notepad ++ не поддерживает использование утверждений отрицательного просмотра назад переменной длины, и было бы неплохо найти обходные пути. Давайте рассмотрим пример в исходном вопросе, но предположим, что мы хотим избежать появления файлов с именем flecha с любым числом цифр после flecha и с любыми символами перед flecha. В этом случае регулярное выражение, использующее отрицательный просмотр назад переменной длины, будет выглядеть как (?<!flecha[0-9]*)\.jpg.

Строки, которые мы не хотим сопоставить в этом примере

  • flecha.jpg
  • flecha1.jpg
  • flecha00501275696.jpg
  • aflecha.jpg
  • img_flecha9.jpg
  • abcflecha556677.jpg

Стратегии

  1. Вставка временных маркеров

    Начните с поиска и замены экземпляров, с которыми вы не хотите работать, - в нашем случае экземпляров flecha[0-9]*\.jpg. Вставьте специальный маркер, чтобы сформировать узор, который больше нигде не появляется. В этом примере мы вставим дополнительный . перед .jpg, предполагая, что ..jpg больше нигде не появляется. Итак, мы делаем:

    Находят: (flecha[0-9]*)(\.jpg)

    Заменить на: $1.$2

    Теперь вы можете искать в документе все остальные .jpg имена файлов с помощью простого регулярного выражения, например \w+\.jpg или (?<!\.)\.jpg, и делать с ними все, что хотите. Когда вы закончите, выполните последнюю операцию поиска и замены, в которой вы замените все экземпляры ..jpg на .jpg, чтобы удалить временный маркер.

  2. Использование утверждения отрицательного просмотра вперед

    Утверждение отрицательного просмотра вперед может использоваться, чтобы убедиться, что вы не сопоставляете нежелательные имена файлов:

    (?<!\S)(?!\S*flecha\d*\.jpg)\S+\.jpg

    Разбивая это:

    • (?<!\S) ensures that your match begins at the start of a file name, and not in the middle, by asserting that your match is not preceded by a non-whitespace character.
    • (?!\S*flecha\d*\.jpg) гарантирует, что все, что соответствует, не содержит шаблон, который мы хотим избежать
    • \S+\.jpg - это то, что фактически соответствует - строка непробельных символов, за которой следует .jpg.
  3. Использование нескольких отрицательных просмотров назад фиксированной длины

    Это быстрое (но не очень элегантное) решение для ситуаций, когда шаблон, которому вы не хотите сопоставлять, имеет небольшое количество возможных длин.

    Например, если мы знаем, что за flecha следует не более трех цифр, наше регулярное выражение может быть таким:

    (?<!flecha)(?<!flecha[0-9])(?<!flecha[0-9][0-9])(?<!flecha[0-9][0-9][0-9])\.jpg

person Josh Withee    schedule 11.02.2018
comment
Ваша стратегия 3 абсолютно спасла мне день. Я знаю, что отправка благодарностей не является целью комментариев, но я думал, что отправлю все равно. Спасибо, @JoshWithee! Всем, кто борется с просмотром вперед / назад переменной длины, я рекомендую попробовать этот неэлегантный, но эффективный подход. - person IggyM; 30.03.2020
comment
Стратегия 1 мне помогла. Спасибо. - person Jonathan Aquino; 28.02.2021

Вы знаете, что сопоставляете (в смысле потребления) только расширение (.jpg)? Я бы подумал, что вы хотите сопоставить полное имя файла, не так ли? А с опережением сделать это намного проще:

\b(?!flecha1?\b)\w+\.jpg

Первый \b привязывает совпадение к началу имени (при условии, что это действительно имя файла, на которое мы смотрим). Затем (?!flecha1?\b) утверждает, что имя не flecha или flecha1. Как только это будет сделано, \w+ продолжит работу и поглотит имя. Затем \.jpg хватает расширение, чтобы закончить матч.

person Alan Moore    schedule 25.06.2013
comment
Как вы заметили, я хочу сопоставить только расширение .jpg. Я только хотел искать любые другие изображения в исходном файле, и мне не нужно знать их имена файлов, только если они вообще встречаются. Но спасибо! ответ обязательно пригодится на будущее =) - person DiegoDD; 25.06.2013