Негативный просмотр, похоже, не работает должным образом

Предположим, PHP-код

/**
 * @since             1.0.0 <--- this shouldn't be matched
 * @package           blah blah blah
 * Version:           1.0.0 <--- this should be matched
 */

/**
 * Fired during plugin activation.
 *
 * This class defines all code necessary to run during the plugin's activation.
 *
 * @since      1.0.0 <--- this shouldn't be matched
 * @package    blah blah
 * @subpackage blah blah
 * @author     blah blah
 */

define( 'PLUGIN_VERSION', '1.0.0' ); // <--- this should be matched

Я хочу сопоставить вхождения 1.0.0, которые не идут после строки @since, поэтому я хочу сопоставить только второе и третье.

Это регулярное выражение должно работать в VS.Code, и я искал этот шаблон (?<!since)(?:\s*)1\.0\.0, который, похоже, не работает. Что мне не хватает?

https://regex101.com/r/BGtDx6/1

Между @since и 1.0.0 есть пробел. В вашем негативном взгляде назад не хватает пробелов.

Barmar 27.08.2024 00:00
regex101.com/r/ka1jjF/1
Barmar 27.08.2024 00:03

Извините, я вставил неправильный шаблон регулярного выражения, а пример регулярного выражения 101 был предыдущей версией. Я обновил свой ответ, который все еще не работает должным образом.

James B. 27.08.2024 00:03

Ваше регулярное выражение не работает должным образом, потому что в других файлах плагина меньше пробелов между @since и 1.0.0.

James B. 27.08.2024 00:05

Почему изменится количество мест? Они выглядят как автоматически созданные комментарии, и я ожидаю, что все они будут одного формата.

Barmar 27.08.2024 00:06

Причина, по которой ваше регулярное выражение не работает, заключается в том, что \s* не обязательно соответствует всем пробелам. Если он соответствует на один пробел меньше, негативного просмотра назад можно избежать, поэтому шаблон совпадает.

Barmar 27.08.2024 00:08

Причину вашего предыдущего вопроса можно увидеть в этих двух примерах: prnt.sc/AWPYexqn4aXF и prnt.sc/F-hqauuqSjhW

James B. 27.08.2024 00:11

Кстати, группу собирать не обязательно \s*

Barmar 27.08.2024 00:12

Так как же это решить, если фиксированной ширины нет?

James B. 27.08.2024 00:12

Я думаю, вы могли бы использовать что-нибудь с \K для сброса . Либо \S(?<!since)\s*\K1\.0\.0 или ^(?!.*since\h*(1\.0\.0)).*\K (?1) или (*SKIP)(*F) : поскольку\h*(1\.0\.0)(*SKIP)(*F)|(?1)

bobble bubble 27.08.2024 00:31

Возможно, этого будет достаточно: поскольку\h*\d(*SKIP)(*F)|1\.0\.0 (по крайней мере, это эффективно!)

bobble bubble 27.08.2024 00:44

@bobblebubble, похоже, это не работает в VS.Code!

James B. 27.08.2024 00:55

@ДжеймсБ. О, я пропустил это требование, увидел только «php» (это шаблоны PCRE/PHP). И вы также хотите сопоставить пробелы, как насчет, например. (?<=\S)(?<!since)\s*1\.0\.0

bobble bubble 27.08.2024 01:02

О боже, вот и все @bobblebubble Пожалуйста, укажите свой последний шаблон в виде отдельного ответа! Это то, что мне было нужно, и оно заслуживает одобрения!

James B. 27.08.2024 01:04

@ДжеймсБ. Рад, что это помогло!

bobble bubble 27.08.2024 01:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
15
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Поскольку количество пробелов неизвестно, один из способов сделать это — отрицать since:

^(?im)\s*\*\s*(?!@since)[a-z]+\s*:\s*1\.0\.0

а затем, используя группу захвата, можно сопоставить 1.0.0:

^(?im)\s*\*\s*(?!@since)[a-z]+\s*:\s*(1\.0\.0)
  • ^: означает начало строки.
  • (?im): означает нечувствительные и многострочные флаги.
  • \s*: означает ноль или более пробелов.
  • \*: буквально *
  • (?!@since): исключает since.
  • [a-z]+: один или несколько символов от A до Z (также можно добавить другие символы)
  • (1\.0\.0): группа захвата, включающая 1.0.0 и к которой можно обращаться как $1

Для использования в среде VS Code следует удалить встроенный флаг:

(?!@since)[\w\s]+:\s*(1\.0\.0)|^\s*\w+\s*\(\s*['"]\s*[^'"]*['"]\s*,\s*['"]\s*([^'"]*)['"]\s*\)\s*;

Кажется, вы пытаетесь выполнить операцию поиска-замены. В этом случае:

  • просто сопоставьте * @since 1.0.0 с помощью простого регулярного выражения (@since\s+(1\.0\.0)) и замените его уникальной строкой, например A0P8x&2%.
  • Затем просто найдите 1.0.0 и внесите изменения.
  • Наконец, замените A0P8x&2% на * @since 1.0.0.

Почему у тебя [a-z]+? После @since букв нет.

Barmar 27.08.2024 00:11

Не работает: regex101.com/r/y8QWW5/1

Barmar 27.08.2024 00:11

@Бармар Я думал, ОП хотел сопоставить Version, а не since?

123 27.08.2024 00:12

@Barmar Флаг многострочности выключен. Исправлено это.

123 27.08.2024 00:13

Я понимаю. Это соответствует ключевым словам, кроме since.

Barmar 27.08.2024 00:14

@Barmar Может быть, кажется, что ОП хочет только исключить since. Спасибо за обращение к флагу m.

123 27.08.2024 00:15

Но суть вашего решения состоит в том, чтобы использовать отрицательный просмотр вперед в начале строки, а не отрицательный просмотр назад перед числом.

Barmar 27.08.2024 00:16

Точно, я хочу, чтобы не сопоставлялись только строки @since.

James B. 27.08.2024 00:16

@Barmar Да, это правильно.

123 27.08.2024 00:19

@ДжеймсБ. Вы также можете использовать что-то более компактное: (?im)(?!@since)[\w\s]+:\s*(1\.0\.0) и ваше совпадение находится в $1.

123 27.08.2024 00:20

@ 123 ваш ответ, похоже, тоже не работает, потому что он не соответствует последней строке (той, что с константой) regex101.com/r/y4sAYi/1 Регулярное выражение должно соответствовать любому вхождению 1.0.0, кроме для тех, у кого есть @since в каком-то месте в одной строке!

James B. 27.08.2024 00:24

Кроме того, ваш шаблон вообще не работает с VS.Code!

James B. 27.08.2024 00:26

@ДжеймсБ. Для использования в коде VS встроенные флаги можно удалить (?!@since)[\w\s]+:\s*(1\.0\.0). Кроме того, define( 'PLUGIN_VERSION', '1.0.0' ); — это еще одно регулярное выражение, которое можно записать и соединить с одним регулярным выражением с помощью канала. Какие еще тест-кейсы у вас есть? Обновите свой вопрос, указав все возможные тестовые примеры.

123 27.08.2024 00:33

Извините @ 123, ваше решение не подходит для моего случая, так как я не могу легко предсказать, какое еще вхождение 1.0.0 может существовать в файлах плагина, чтобы объединить их все с помощью канала. Вот почему я попросил что-то, что будет соответствовать любой версии 1.0.0, кроме тех, которые имеют @since в одной строке. Если это невозможно, мне придется вручную выполнить работу, для которой мне нужен шаблон.

James B. 27.08.2024 00:36

@ДжеймсБ. Что ж, в этом случае просто сопоставьте * @since 1.0.0 и замените его уникальной строкой, например A0P8x&2%. Затем просто найдите 1.0.0 и внесите изменения. Затем замените A0P8x&2% на * @since 1.0.0. Вам не понадобится регулярное выражение.

123 27.08.2024 00:41

@ 123, это был мой первый подход, но есть 77 случаев @since 1.0.0, но есть 4 разных варианта использования пробелов между с момента и 1.0.0... 57 используют 4 пробела, 3 используют 5, 16 используют 6 и 1 использует 13. Вот почему я подумал, что было бы проще каким-то образом игнорировать все 77 вхождений одновременно, вместо того, чтобы заменять каждый вариант другой строкой, затем манипулировать оставшимися допустимыми, а затем возвращать строки к соответствующим вариантам! Странно, что у этого нет простого (или вообще нет) решения с помощью регулярных выражений!

James B. 27.08.2024 00:53

@ДжеймсБ. Ваш первый подход лучше. Используйте @since\s+(1\.0\.0) и замените его на A0P8x&2%, затем внесите изменения в 1.0.0. Наконец, замените A0P8x&2% на @since (1\.0\.0). Количество мест не имеет значения.

123 27.08.2024 00:57

Это не сработает, поскольку все варианты пробелов будут заменены одной и той же строкой, и тогда я не смогу отменить замены с другим количеством пробелов!

James B. 27.08.2024 01:02

@ДжеймсБ. Зачем вам нужно точное количество пробелов? Если да, то используйте 4 уникальные строки для 4 разных вариантов и внесите изменения. В противном случае подождите, возможно, у кого-то есть лучшее решение.

123 27.08.2024 01:07

@123, потому что это нарушит выравнивание комментариев, например: prnt.sc/AWPYexqn4aXF и prnt.sc/F-hqauuqSjhW

James B. 27.08.2024 01:11
Ответ принят как подходящий

Вы можете добавить еще один просмотр назад, чтобы оглядываться назад только там, где раньше не было пробелов:

(?<!\s)(?<!since)\s*1\.0\.0

Посмотрите эту демонстрацию на сайте regex101

Это предотвратит успех последнего просмотра назад там, где ему предшествует пробел.
При необходимости вы можете захватить пробелы и повторно вставить в строку замены вот так.

Это было именно то, что мне нужно! Огромное вам спасибо за это!

James B. 27.08.2024 01:12

@ДжеймсБ. Добро пожаловать! Я изменил свой ответ с положительного просмотра (?<=\S) на отрицательный вариант (?<!\s), который также может соответствовать 1.0.0 в начале строки.

bobble bubble 27.08.2024 02:04

Другие вопросы по теме

Объединить многострочные строки в фрейме данных pandas на основе шаблона регулярного выражения
Регулярное выражение для текста, разделенного запятыми, с необязательными двойными кавычками, которые могут содержать кавычки, экранированные обратной косой чертой
Почему эта замена регулярного выражения с использованием захвата зависает в этом быстром коде?
Токенизация XSLT с помощью регулярного выражения для токенизации только в том случае, если за точкой с запятой не следует пробел и число
Regex соответствует определенным шаблонам URL-адресов
Используйте одно регулярное выражение для извлечения информации из двух шаблонов
Регулярное выражение для соответствия начальной нумерации или алфавитным маркерам, например (a)
Как включить проверку наличия большего количества пробелов в негативном виде?
Анализ регулярных выражений "^[-\wÀ-ÿ\'\.\-\&\s]+$" - диапазон [x-y] в обратном порядке
Как игнорировать ключевые слова в регулярном выражении перед переменными?