パターンが一致したことに驚きましたが、誰も説明しませんでしたか? パターンの一致方法は次のとおりです。
my @matches = $str =~ /\{(?:\{.*\}|[^{])*\}|\w+/sg;
^ ^ ^ ^ ^ ^
| | | | | |
{ ---------------------+ | | | | |
a --------------------------)-)-)--+ |
b --------------------------)-)-)--+ |
c --------------------------)-)-)--+ |
} --------------------------)-)-)--+ |
--------------------------)-)-)--+ |
{ --------------------------+ | | |
{ ----------------------------+ | |
x ----------------------------+ | |
y ----------------------------+ | |
z ----------------------------+ | |
} ------------------------------+ |
} ----------------------------------------+
ご覧のとおり、問題は / \{.*\}
/ が一致しすぎることです。そこにあるべきものは一致するものです
(?: \s* (?: \{ ... \} | \w+ ) )*
どこに...
ある
(?: \s* (?: \{ ... \} | \w+ ) )*
したがって、再帰が必要です。名前付きグループは、これを行う簡単な方法です。
say $1
while /
\G \s*+ ( (?&WORD) | (?&BRACKETED) )
(?(DEFINE)
(?<WORD> \s* \w+ )
(?<BRACKETED> \s* \{ (?&TEXT)? \s* \} )
(?<TEXT> (?: (?&WORD) | (?&BRACKETED) )+ )
)
/xg;
しかし、車輪を再発明する代わりに、Text::Balancedを使用しない理由はありません。