Регулярное выражение: сопоставлять только неповторяющееся вхождение символа

#regex

#регулярное выражение

Вопрос:

Мне нужно найти и заменить все вхождения символа-апострофа в строке, но только если за этим апострофом не следует другой апостроф.

Это

abc’def

является совпадением, но

abc»def

не соответствует.

Я уже составил рабочий шаблон — (^|[^'])'($|[^']) но я полагаю, что он может быть короче и проще.

Спасибо,

Валерий

Комментарии:

1. нравится это?? rubular.com/r/5oHGVS3r1c

2. Что это за среда? Perl? Javascript? PHP? Java? POSIX? Не все синтаксисы регулярных выражений одинаковы.

Ответ №1:

зависит от вашей среды — если ваша среда поддерживает просмотр вперед и назад, вы можете сделать это: (?<!')'(?!')

Ссылка:http://www.regular-expressions.info/lookaround.html

Ответ №2:

Я думаю, что ваш шаблон короткий и точный. Вы могли бы использовать отрицательный прогноз / lookbehind, но они сделали бы это намного сложнее. Важна ремонтопригодность.

Комментарии:

1. да, я использую regexp годами и только вчера потратил время на то, чтобы разобраться в lookahead и lookbehind, из-за вопроса stackoverflow. Вероятно, это говорит больше обо мне, чем о функции, но суть в том, что исходная версия понятна, даже если у вас есть более базовые знания о regexp, и согласована во всех средах.

2. @Tao: Это именно то, о чем я говорю 🙂

3. Полностью согласен, хотя приведенный выше пример lookahead / lookbehind хорош, краток и корректен, моя собственная примитивная версия проще для понимания разработчикам, не разбирающимся в регулярных выражениях. Все еще сомневаетесь, какой подход использовать 🙂

Ответ №3:

Вам придется быть осторожным с неравномерным количеством апострофов:

 abc'''def
  

где вы, вероятно, действительно хотите заменить 3-й и оставить там 1-й и 2-й.

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

Поиск шаблона:

 (('')*)'
  

и замените его на

 $1
  

что является группой 1: четные апострофы (или вообще без апостроф).

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

Комментарии:

1. Нет, это не CSV. На самом деле я решал проблему с классом Java MessageFormat, который проглатывает один символ апострофа.

Ответ №4:

смотрите здесь нагативный поиск q(?!u)

  • (?=pattern) является положительным прогнозным утверждением
  • (?!pattern) является отрицательным прогнозным утверждением
  • (?<=pattern) является положительным утверждением о проверке
  • (?<!pattern) является отрицательным утверждением, лежащим в основе

http://www.regular-expressions.info/lookaround.html

рабочая ДЕМОНСТРАЦИЯ