Нужно избегать несбалансированных скобок в моем регулярном выражении perl - PullRequest
0 голосов
/ 29 апреля 2018
  • Редактировать: я добавил ссылку на инструмент регулярных выражений, чтобы проверить регулярное выражение в действии: https://regex101.com/r/906a6D/4

У меня есть следующее регулярное выражение perl

/(\[(?>[^\[\]]+|(?1))*\])/sg

Это прекрасно работает и полностью соответствует всем этим строкам

[a ] 

[ a] 

[a [b
]] 

[code sub t{
   my ($o,$k) = @_;
   my $c = 0;
   my $r;
   for(split //,$t){
     $r .= $_ unless(($c+($k-$o)) % $k);
     []
     $c++
   }
   $r =~ s/[^a-z]//g;
   return $r
 }]

Однако мне нужно выйти за скобки. Если есть несбалансированные, это не сработает, поэтому я хотел бы избежать их как \] или, может быть, как {{- ] -}}.

Это должно соответствовать до последней] скобки.

[a \] ]        

Это должно совпадать до последнего ].

[a \]\[ ]      

Это тоже

[a \\ ]        

Я также пытался использовать обходные утверждения (?>!), (?<=) перед внешними скобками и с внутренними игнорируемыми скобками, но затем строки, подобные этой

[a \[ ]    

Полностью игнорируются, абсолютно не имеют себе равных, даже один символ.

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

1 Ответ

0 голосов
/ 29 апреля 2018

Вот возможное решение:

m{ ( \[ (?> [^\[\]\\]++ | \\. | (?1) )*+ \] ) }xs

Изменения:

  • добавлен флаг x, чтобы сделать его более читабельным
  • сделал все квантификаторы собственническими, потому что почему бы и нет (в противном случае я бы чувствовал себя неловко из-за вложенных квантификаторов (+ непосредственно внутри *))
  • добавил \ к первому символьному классу, чтобы предотвратить его сопоставление (например, [ и ], \ имеет особое значение для нашего регулярного выражения)
  • добавлена ​​ветвь для экранированных символов (\, за которыми следуют любые символы, но другие игнорируются)
...