Каков наиболее эффективный способ заставить отрицательный ретроспективный анализ работать вместе с необязательным значением?

Я знаю, что отрицательный просмотр назад должен иметь нулевую ширину, но я заметил проблему, из-за которой они не работают, если предыдущий токен является необязательным. Почему это происходит?

(?<!test):?(\\d{3})

Сбой на test123. Но проходит test:123

Есть ли решение этой проблемы, кроме (?<!test|test:)? Я бы предпочел избежать приведенного выше решения, поскольку регулярное выражение, к которому я хотел бы применить это, уже имеет много негативных фраз просмотра, которые я бы удвоил.

Редактировать: изначально я разместил это с помощью редактора PCRE, но я кодирую с помощью ICU


person Declan McKenna    schedule 21.03.2016    source источник
comment
Я использую онлайн-тестер PCRE для своих выражений ICU, а затем просто добавляю дополнительные обратные косые черты, так что любой из них подходит для меня. Я получаю те же результаты в моем быстром регулярном выражении ICU и веб-приложении PCRE. С веб-приложением гораздо проще делиться и экспериментировать.   -  person Declan McKenna    schedule 21.03.2016
comment
С ICU вы можете использовать (?<!test:{0,1})\d{3}.   -  person Wiktor Stribiżew    schedule 21.03.2016
comment
Это работает, спасибо. Это первое отличие, с которым я столкнулся, кроме дополнительной обратной косой черты. Я, вероятно, должен найти редактора ICU. Не стесняйтесь указывать это в качестве ответа. Я отредактирую вопрос, чтобы удалить ссылки на PCRE, чтобы избежать путаницы.   -  person Declan McKenna    schedule 21.03.2016
comment
Обратите внимание, что регулярное выражение ICU не работает так же, как PCRE, вы должны знать о различиях при тестировании в несовместимой среде, такой как regex101.com.   -  person Wiktor Stribiżew    schedule 21.03.2016


Ответы (1)


С механизмом регулярных выражений ICU у вас есть доступ к ретроспективному анализу ограниченной ширины, который позволяет использовать ограничивающие квантификаторы известной длины внутри ретроспективного анализа.

Итак, используйте

(?<!test:{0,1})\d{3}
        ^^^^^^

:{0,1} будет соответствовать одному или нулю :.

Обратите внимание, что регулярное выражение ICU не работает так же, как PCRE, вы должны знать о различиях при тестировании в несовместимой среде, такой как regex101.com.

Некоторые интересные функции PCRE, которых нет в ICU:

  • (*SKIP)(*FAIL) глаголов
  • \K оператор

Некоторые интересные функции ICU отсутствуют в PCRE:

  • Ограниченный поиск по ширине ((?<!test:{0,1})\d{3})
  • Пересечение классов символов ([\p{Letter}&&\p{script=cyrillic}]) или вычитание ([\p{Letter}--\p{script=latin}])
person Wiktor Stribiżew    schedule 21.03.2016