Предположим, 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
, который, похоже, не работает. Что мне не хватает?
Извините, я вставил неправильный шаблон регулярного выражения, а пример регулярного выражения 101 был предыдущей версией. Я обновил свой ответ, который все еще не работает должным образом.
Ваше регулярное выражение не работает должным образом, потому что в других файлах плагина меньше пробелов между @since и 1.0.0.
Почему изменится количество мест? Они выглядят как автоматически созданные комментарии, и я ожидаю, что все они будут одного формата.
Причина, по которой ваше регулярное выражение не работает, заключается в том, что \s*
не обязательно соответствует всем пробелам. Если он соответствует на один пробел меньше, негативного просмотра назад можно избежать, поэтому шаблон совпадает.
Причину вашего предыдущего вопроса можно увидеть в этих двух примерах: prnt.sc/AWPYexqn4aXF и prnt.sc/F-hqauuqSjhW
Кстати, группу собирать не обязательно \s*
Так как же это решить, если фиксированной ширины нет?
Я думаю, вы могли бы использовать что-нибудь с \K для сброса . Либо \S(?<!since)\s*\K1\.0\.0 или ^(?!.*since\h*(1\.0\.0)).*\K (?1) или (*SKIP)(*F) : поскольку\h*(1\.0\.0)(*SKIP)(*F)|(?1)
Возможно, этого будет достаточно: поскольку\h*\d(*SKIP)(*F)|1\.0\.0 (по крайней мере, это эффективно!)
@bobblebubble, похоже, это не работает в VS.Code!
@ДжеймсБ. О, я пропустил это требование, увидел только «php» (это шаблоны PCRE/PHP). И вы также хотите сопоставить пробелы, как насчет, например. (?<=\S)(?<!since)\s*1\.0\.0
О боже, вот и все @bobblebubble Пожалуйста, укажите свой последний шаблон в виде отдельного ответа! Это то, что мне было нужно, и оно заслуживает одобрения!
@ДжеймсБ. Рад, что это помогло!
Поскольку количество пробелов неизвестно, один из способов сделать это — отрицать 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
букв нет.
Не работает: regex101.com/r/y8QWW5/1
@Бармар Я думал, ОП хотел сопоставить Version
, а не since
?
@Barmar Флаг многострочности выключен. Исправлено это.
Я понимаю. Это соответствует ключевым словам, кроме since
.
@Barmar Может быть, кажется, что ОП хочет только исключить since
. Спасибо за обращение к флагу m
.
Но суть вашего решения состоит в том, чтобы использовать отрицательный просмотр вперед в начале строки, а не отрицательный просмотр назад перед числом.
Точно, я хочу, чтобы не сопоставлялись только строки @since.
@Barmar Да, это правильно.
@ДжеймсБ. Вы также можете использовать что-то более компактное: (?im)(?!@since)[\w\s]+:\s*(1\.0\.0)
и ваше совпадение находится в $1
.
@ 123 ваш ответ, похоже, тоже не работает, потому что он не соответствует последней строке (той, что с константой) regex101.com/r/y4sAYi/1 Регулярное выражение должно соответствовать любому вхождению 1.0.0, кроме для тех, у кого есть @since
в каком-то месте в одной строке!
Кроме того, ваш шаблон вообще не работает с VS.Code!
@ДжеймсБ. Для использования в коде VS встроенные флаги можно удалить (?!@since)[\w\s]+:\s*(1\.0\.0)
. Кроме того, define( 'PLUGIN_VERSION', '1.0.0' );
— это еще одно регулярное выражение, которое можно записать и соединить с одним регулярным выражением с помощью канала. Какие еще тест-кейсы у вас есть? Обновите свой вопрос, указав все возможные тестовые примеры.
Извините @ 123, ваше решение не подходит для моего случая, так как я не могу легко предсказать, какое еще вхождение 1.0.0 может существовать в файлах плагина, чтобы объединить их все с помощью канала. Вот почему я попросил что-то, что будет соответствовать любой версии 1.0.0, кроме тех, которые имеют @since
в одной строке. Если это невозможно, мне придется вручную выполнить работу, для которой мне нужен шаблон.
@ДжеймсБ. Что ж, в этом случае просто сопоставьте * @since 1.0.0
и замените его уникальной строкой, например A0P8x&2%
. Затем просто найдите 1.0.0
и внесите изменения. Затем замените A0P8x&2%
на * @since 1.0.0
. Вам не понадобится регулярное выражение.
@ 123, это был мой первый подход, но есть 77 случаев @since 1.0.0
, но есть 4 разных варианта использования пробелов между с момента и 1.0.0... 57 используют 4 пробела, 3 используют 5, 16 используют 6 и 1 использует 13. Вот почему я подумал, что было бы проще каким-то образом игнорировать все 77 вхождений одновременно, вместо того, чтобы заменять каждый вариант другой строкой, затем манипулировать оставшимися допустимыми, а затем возвращать строки к соответствующим вариантам! Странно, что у этого нет простого (или вообще нет) решения с помощью регулярных выражений!
@ДжеймсБ. Ваш первый подход лучше. Используйте @since\s+(1\.0\.0)
и замените его на A0P8x&2%
, затем внесите изменения в 1.0.0
. Наконец, замените A0P8x&2%
на @since (1\.0\.0)
. Количество мест не имеет значения.
Это не сработает, поскольку все варианты пробелов будут заменены одной и той же строкой, и тогда я не смогу отменить замены с другим количеством пробелов!
@ДжеймсБ. Зачем вам нужно точное количество пробелов? Если да, то используйте 4 уникальные строки для 4 разных вариантов и внесите изменения. В противном случае подождите, возможно, у кого-то есть лучшее решение.
@123, потому что это нарушит выравнивание комментариев, например: prnt.sc/AWPYexqn4aXF и prnt.sc/F-hqauuqSjhW
Вы можете добавить еще один просмотр назад, чтобы оглядываться назад только там, где раньше не было пробелов:
(?<!\s)(?<!since)\s*1\.0\.0
Посмотрите эту демонстрацию на сайте regex101
Это предотвратит успех последнего просмотра назад там, где ему предшествует пробел.
При необходимости вы можете захватить пробелы и повторно вставить в строку замены вот так.
Это было именно то, что мне нужно! Огромное вам спасибо за это!
@ДжеймсБ. Добро пожаловать! Я изменил свой ответ с положительного просмотра (?<=\S)
на отрицательный вариант (?<!\s)
, который также может соответствовать 1.0.0
в начале строки.
Между
@since
и1.0.0
есть пробел. В вашем негативном взгляде назад не хватает пробелов.