Упреждающие/упреждающие комментарии регулярных выражений

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

(?<!=#)test\.this\.regex\s+\"(.*?)\"

Я чувствую, что это должно работать? Я прочитал это так:

(?<!=#) посмотрите назад, чтобы убедиться, что ему не предшествует #

test\.this\.regex\s+\"(.*?)\" соответствует test.this.regex "sup1"

Вот фрагмент конфигурации

    test.this.regex "sup1" hi |sup1| # test.this.regex "sup3" hi |sup3|
# test.this.regex "sup2" do |sup2|
    test.this.regex "sup2" do |sup2|

Но мое регулярное выражение соответствует всем 4 раза:

Match 1
1.  sup1
Match 2
1.  sup3
Match 3
1.  sup2
Match 4
1.  sup2

person bruchowski    schedule 17.05.2014    source источник
comment
Какой язык/инструмент вы используете для этого?   -  person anubhava    schedule 17.05.2014
comment
Кажется, после # есть пробел, который вы не учли в своем регулярном выражении.   -  person Anirudh Ramanathan    schedule 17.05.2014
comment
Синтаксис отрицательного взгляда назад: (?<!...), а не (?<!=...).   -  person Casimir et Hippolyte    schedule 17.05.2014
comment
@anubhava Я использую этот rubular.com, так как он поддерживает просмотр вперед и назад   -  person bruchowski    schedule 17.05.2014
comment
@CasimiretHippolyte не имеет значения   -  person bruchowski    schedule 17.05.2014
comment
Это потому, что вы забыли пространство.   -  person Casimir et Hippolyte    schedule 17.05.2014
comment
@DarkCthulhu это определенно причина, но как мне проверить что-нибудь между # и строкой, которую я хочу сопоставить? Пробовал .* после # и до test не работает   -  person bruchowski    schedule 17.05.2014
comment
@bruchowski: всегда полезно указать, на каком языке. Тег ruby, rubular, отрицательный-lookbehind. Ретегируйте как хотите.   -  person smci    schedule 17.05.2014
comment
@smci спасибо, сделаю в будущем   -  person bruchowski    schedule 17.05.2014


Ответы (2)


Вы можете использовать это регулярное выражение PCRE:

/(?># *(*SKIP)(*FAIL)|(?:^|\s))test\.this\.regex\s+\"[^"]*\"/

Рабочая демонстрация

  • (*FAIL) ведет себя как ошибочное отрицательное утверждение и является синонимом (?!).
  • (*SKIP) определяет точку, после которой движку регулярных выражений не разрешается отступать, если позже подшаблон дает сбой.
  • (*SKIP)(*FAIL) вместе обеспечивают хорошую альтернативу ограничению, заключающемуся в том, что вы не можете иметь переменную длину lookbehinf в приведенном выше регулярном выражении.

ОБНОВЛЕНИЕ: не уверен, поддерживает ли ruby ​​(*SKIP)(*FAIL), поэтому даю эту альтернативную версию:

(?:# *test\.this\.regex\s+\"[^"]*\"|\b(test\.this\.regex\s+\"[^"]*\"))

И ищите непустую совпадающую группу №1.

Рабочая демонстрация 2

person anubhava    schedule 17.05.2014
comment
Это ломается, если после # есть более одного пробела - person bruchowski; 17.05.2014
comment
Уточните это в своем вопросе, и именно поэтому я спросил, какой язык вы используете? - person anubhava; 17.05.2014
comment
Я думал, что сделал это в первом предложении, извините, если вы это пропустили; Я также отметил, что использую реализацию регулярных выражений Ruby. Он должен совпадать, если между # и test.this.regex есть что-то, так как это означает, что это комментарий, и я хочу игнорировать это совпадение. - person bruchowski; 17.05.2014
comment
Смотрите обновленный ответ. Ваш вопрос должен быть помечен языком/инструментом в дополнение к регулярному выражению. - person anubhava; 17.05.2014
comment
У меня было это раньше, (#)?.*test\.this\.regex\s+\"(.*)\" но я надеялся, что смогу сопоставить только те строки, которые мне нужны, только с одной группой захвата - person bruchowski; 17.05.2014
comment
(#)?.*test\.this\.regex\s+\"(.*)\" не поможет, так как он будет соответствовать обеим строкам, и вы не можете использовать динамическую длину в ретроспективном просмотре. - person anubhava; 17.05.2014
comment
cannot have dynamic length in lookbehind этого недостающего элемента, спасибо, я этого не знал - person bruchowski; 17.05.2014
comment
Я считаю, что кроме .NET никакой другой язык не поддерживает динамическую длину lookbehinds. - person anubhava; 17.05.2014

Если ваш вопрос заключен в первом предложении (а не конкретно об обходах), почему бы вам просто не использовать String#split с вашим регулярным выражением без просмотра назад?

def doit(str)
  r = /test\.this\.regex\s+\"(.*?)\"/
  str.split('#').first[r,1]
end

doit('test.this.regex "sup1" hi |sup1| # test.this.regex "sup3" hi |sup3|')
  #=> "sup1"
doit('# test.this.regex "sup2" do |sup2|')
  #=> nil
doit('test.this.regex "sup2" do |sup2|')
  #=> "sup2"
person Cary Swoveland    schedule 17.05.2014