Как сделать отрицательный взгляд в пределах% r <…> регулярного выражения в Ruby? - PullRequest
9 голосов
/ 25 апреля 2019

Мне нравятся разделители %r<…>, потому что с их помощью действительно легко определить начало и конец регулярного выражения, и мне не нужно избегать каких-либо /. Но кажется, что у них есть непреодолимое ограничение, которого нет у других разделителей?

Все остальные мыслимые разделители работают нормально:

/(?<!foo)/
%r{(?<!foo)}
%r[(?<!foo)]
%r|(?<!foo)|
%r/(?<!foo)/

Но когда я пытаюсь сделать это:

%r<(?<!foo)>

выдает синтаксическую ошибку:

unterminated regexp meets end of file

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

Нужно ли что-нибудь избежать?

Согласно wikibooks.org :

В качестве разделителя можно использовать любой отдельный не буквенно-цифровой символ, %[including these], %?or these?, %~or even these things~. Используя это обозначение, могут появиться обычные разделители строк "и" в строке unescaped, но, конечно, новый разделитель, который вы выбрали нужно сбежать.

Действительно, экранирование необходимо в следующих примерах:

%r!(?<\!foo)!                                                             
%r?(\?<!foo)? 

Но если бы это была единственная проблема, тогда я мог бы уйти от этого и заставить это работать:

%r<(?\<!foo)>

Но это приводит к этой ошибке:

undefined group option: /(?\<!foo)/

Так, может быть, экранирование не необходимо / разрешено? wikibooks.org перечисляет %<pointy brackets> как одно из исключений:

Однако, если вы используете %(parentheses), %[square brackets], %{curly brackets} или %<pointy brackets> как разделители, так и те же разделители может отображаться в строке без экранирования , если они находятся в сбалансированном пар

Это проблема с сбалансированными парами?

Сбалансированные пары - не проблема, если вы делаете что-то в регулярном выражении, которое требует их, например ...

%r{(?<!foo{1})}   # repetition quantifier
%r[(?<![foo])]    # character class
%r<(?<name>foo)>  # named capture group

Но что если вам нужно вставить разделитель слева ({, [или <) внутри регулярного выражения? Просто избегай этого, верно? В Ruby, похоже, нет проблем с экранированными несбалансированными разделителями <em>в большинстве случаев ...

%r{(?<!foo\{)}                                                                  
%r[(?<!\[foo)]
%r<\<foo>

Это просто когда вы пытаетесь сделать это в середине «опций группы» (что, я думаю, означает то, что символы <! классифицируются как здесь) после (?, ему это не нравится:

%r<(?\<!foo)>
# undefined group option: /(?\<!foo)/

Так как же вы тогда делаете это и делаете Руби счастливым? (без изменения разделителей)

Заключение

Обойти это легко. Я просто изменю это регулярное выражение, чтобы вместо него использовать что-то другое, например %r{…}.

Но вопросы остаются ...

  1. Неужели нет способа убежать от < здесь?
  2. Действительно ли есть регулярные выражения, которые просто невозможно написать, используя определенные разделители, такие как %r<…>?
  3. Является %r<…> единственной парой регулярных выражений, которая имеет эту проблему (где некоторые регулярные выражения невозможно записать при ее использовании). Если вам известен подобный пример с %r{…} / %r[…], поделитесь!

Информация о версии

Не то чтобы это, вероятно, имеет значение, поскольку этот синтаксис, вероятно, не изменился, но я использую:

⟫ ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]

Справка:

1 Ответ

0 голосов
/ 22 июля 2019

Как уже упоминали другие, это похоже на недосмотр, основанный на том, как этот персонаж отличается от других парных границ.

Что касается "Неужели нет способа избежать <здесь?" есть способ ... но он тебе не понравится: </p>

%r<(?#{'<'}!foo)> == %r((?<!foo))

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...