Perl:从内到外打开列表不起作用?

bar*_*ter 2 perl

$all="{this, {is, some, {deeply, nested}, text}, for, you}";
while ($all=~s/{([^{}]*?)}/f($1)/seg) {}
sub f {return \{split(",",$_[0])};}
print @{$all};
Run Code Online (Sandbox Code Playgroud)

我希望$ all是一个listref,其列表包含:

{this, [reference to array], for, you}
Run Code Online (Sandbox Code Playgroud)

相反,@ {$ all}是空的.

我确信这是基本的,但我做错了什么?

注意:我有意"高举"代码在这里发布(即显示问题的最小代码).更广泛的版本是:https://github.com/barrycarter/bcapps/blob/master/playground.pl

编辑:感谢所有回答的人!笔记:

  • 真正的f()有副作用,更新dbs等,所以我真的必须调用它.它不仅仅是将列表更改为其他内容.我不好意思没有提到这一点.

  • 我从Mathematica导出所以"{a,b,c}"是一个列表,而不是哈希.再次,mea culpa没有提到这一点.

  • 我知道执行此操作的"正常"方式是递归的:处理每个元素,如果元素是列表,则在列表本身上调用f().我试图"展开"递归以避免拆分嵌套的"{".如果你在里面工作,你就不必在解析时计算"{".

  • 一个有趣的其他应用程序将是一个单行的XML解析器(差不多).

  • 给geekosaur一个复选标记,指出哪里出错了,为什么我的方法可能是错误的.

  • 我想我会尝试解析器方法,甚至是jrey的s/{/ [方法.

gee*_*aur 5

你不能$all同时成为一个迭代匹配的字符串一个收集迭代结果的arrayref. $all将最终变成类似于字符串的东西"thisARRAY(0xdeadbeef)foryou",并将@$all其用作包符号名称,几乎肯定没有定义,因此它将自动归档为空列表.

另外,{}已经是(HASH而不是ARRAY)引用,所以你将SCALARref 返回HASHref而不是ARRAYref,正如你所期望的那样.并且{}在正则表达式中是特殊的(foo{1,3}意味着重复1到3次foo),所以你应该逃避它们.

正确的方法是收集到结果列表中,例如

my @res;
while ($all =~ /\G\{([^{}]*?)\}/sg) {
    push @res, f($1);
}
Run Code Online (Sandbox Code Playgroud)

use warnings并且use strict会告诉你一些事情是错的,如果不是确切的话.使用它们.总是.

  • 阿门.严格.阿门.警告 (3认同)