Рекурсивные регулярные выражения понимают именованные захваты? В документах для (?{{ code }})
есть примечание о том, что это независимый подшаблон со своим собственным набором захватов, которые отбрасываются при выполнении подшаблона, и там есть примечание в (?PARNO)
, что его "похоже на (?{{ code }})
. Is (?PARNO)
отказаться от своих собственных именных снимков, когда это будет сделано?
Я пишу о рекурсивных регулярных выражениях Perl для Освоение Perl. perlre уже есть пример со сбалансированными parens (я показываю его в Соответствие сбалансированной круглой скобки в Perl regex), поэтому я решил попробовать сбалансированные кавычки:
#!/usr/bin/perl
# quotes-nested.pl
use v5.10;
$_ =<<'HERE';
He said 'Amelia said "I am a camel"'
HERE
say "Matched!" if m/
(
['"]
(
(?:
[^'"]+
|
( (?1) )
)*
)
['"]
)
/xg;
print "
1 => $1
2 => $2
3 => $3
4 => $4
5 => $5
";
Это работает, и две кавычки отображаются в $1
и $3
:
Matched!
1 => 'Amelia said "I am a camel"'
2 => Amelia said "I am a camel"
3 => "I am a camel"
4 =>
5 =>
Это хорошо. Я это понимаю. Однако я не хочу знать цифры. Итак, я делаю первую группу захвата именованным захватом и смотрю в %-
, ожидая увидеть две подстроки, которые я ранее видел в $1
и $2
:
use v5.10;
$_ =<<'HERE';
He said 'Amelia said "I am a camel"'
HERE
say "Matched [$+{said}]!" if m/
(?<said>
['"]
(
(?:
[^'"]+
|
(?1)
)*
)
['"]
)
/xg;
use Data::Dumper;
print Dumper( \%- );
Я вижу только первое:
Matched ['Amelia said "I am a camel"']!
$VAR1 = {
'said' => [
'\'Amelia said "I am a camel"\''
]
};
Я ожидал, что (?1)
повторит все в первой группе захвата, включая именованный захват, на said
. Я могу исправить это, назвав новый захват:
use v5.10;
$_ =<<'HERE';
He said 'Amelia said "I am a camel"'
HERE
say "Matched [$+{said}]!" if m/
(?<said>
['"]
(
(?:
[^'"]+
|
(?<said> (?1) )
)*
)
['"]
)
/xg;
use Data::Dumper;
print Dumper( \%- );
Теперь я получаю то, что ожидал:
Matched ['Amelia said "I am a camel"']!
$VAR1 = {
'said' => [
'\'Amelia said "I am a camel"\'',
'"I am a camel"'
]
};
Я подумал, что могу исправить это, переместив названный захват на один уровень:
use v5.10;
$_ =<<'HERE';
He said 'Amelia said "I am a camel"'
HERE
say "Matched [$+{said}]!" if m/
(
(?<said>
['"]
(
(?:
[^'"]+
|
(?1)
)*
)
['"]
)
)
/xg;
use Data::Dumper;
print Dumper( \%- );
Но это не поймает меньшую подстроку в said
либо:
Matched ['Amelia said "I am a camel"']!
$VAR1 = {
'said' => [
'\'Amelia said "I am a camel"\''
]
};
Думаю, я это понимаю, но я также знаю, что здесь есть люди, которые на самом деле касаются кода C, который делает это возможным.:)
И, как я пишу это, я думаю, что мне нужно перегрузить галочку STORE для %-
, чтобы узнать, но тогда мне нужно будет выяснить, как это сделать.