2010-08-25 5 views
12

Как написать регулярное выражение, которое соответствует шаблону, который может содержать кавычки, но если это так, должны иметь соответствующие кавычки в начале и конце?Как мне сопоставить шаблон с дополнительными кавычками?

"?(pattern)"? 

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

"(pattern)"|(pattern) 

Будет работать, но повторяется. Есть ли лучший способ сделать это, не повторяя шаблон?

+1

Какой вкус регулярных выражений вы используете? .Net допускает такое «совпадение скобок», но другие ароматы этого не делают. – cristobalito

+0

Связанное исследование: http://stackoverflow.com/questions/3165755/capturing-thispartonly-and-thispartonly-with-the-same-group – polygenelubricants

ответ

17

Вы можете получить решение, не повторяя путем использования backreferences и conditionals:

/^(")?(pattern)(?(1)\1|)$/ 

Матчи:

  • шаблон
  • "узор"

не ли матч:

  • "образец
  • картины"

Этот шаблон является довольно сложным, однако. Сначала он ищет необязательную цитату и помещает ее в backreference 1, если ее можно найти. Затем он ищет ваш шаблон. Затем он использует условный синтаксис, чтобы сказать «если backreference 1 найден снова, сопоставьте его, иначе ничего не получится». Весь шаблон - anchored (что означает, что он должен появляться сам по себе на линии), так что непревзойденные кавычки не будут захвачены (в противном случае pattern в pattern").

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


Update: Намного проще вариант этого регулярное выражение будет /^(")?(pattern)\1$/, который не нуждается в условна. Когда я тестировал это изначально, тестер, который я использовал, дал мне ложный отрицательный результат, который привел меня к скидке (oops!).

Я оставлю решение с условием для потомков и интересов, но это более простая версия, которая, скорее всего, будет работать в более широком спектре движков (обратные ссылки являются единственной функцией, используемой здесь, которая может быть неподдерживаемой).

+0

Aaarrg, я только начал искать регулярное выражение, если условный синтаксис в книге Фриделя , Вы были быстрее +1 (следующий +1 для рекурсивного шаблона ;-) –

+0

@ rubber Когда-то я знал, как делать рекурсивное регулярное выражение, но я думаю, что забыл о пользе человечества;) –

+0

@ Даниэль: Человечество возможно не возражал бы, если бы вы тоже забыли об условностях. '^ ("?) pattern \ 1 $ 'работает просто отлично. (Удаленный ответ @ wuputah не работал, потому что он не был привязан. И @Tim, притяжательные кванторы/атомные группы не нужны.) –

0

В зависимости от языка, который вы используете, вы можете использовать обратные ссылки. Что-то вроде этого, говорят:

(["'])(pattern)\1|^(pattern)$ 

Таким образом, вы требуя, либо нет цитат, или, что то же котировка используется на обоих концах.

0

Это должно работать с рекурсивным регулярным выражением (которое требует больше времени для правильного выбора). Тем временем: в Perl вы можете создать самоописывающееся регулярное выражение .Я оставлю это в качестве учебного примера ;-)

my @stuff = ('"pattern"', 'pattern', 'pattern"', '"pattern' ); 

foreach (@stuff) { 
    print "$_ OK\n" if /^ 
         (")? 
         \w+ 
         (??{defined $1 ? '"' : ''}) 
         $ 
         /x 
} 

Результат:

"pattern" OK 
pattern OK