$all="{this, {is, some, {deeply, nested}, text}, for, you}";
while ($all=~s/{([^{}]*?)}/f($1)/seg) {}
sub f {return \{split(",",$_[0])};}
print @{$all};
我希望$ all是listref,其列表包含:
{this, [reference to array], for, you}
相反,@ {$ all}为空。
我确信这是基本的,但我做错了什么?
注意:我故意“高举”代码在这里发布(即显示问题的最小代码)。更广泛的版本位于:https://github.com/barrycarter/bcapps/blob/master/playground.pl
编辑:感谢所有回答的人!注意:真正的f()有副作用,更新dbs等,所以我真的必须调用它。它不仅仅是 将列表更改为其他内容。我不好意思没有提到这一点。
我从Mathematica导出所以“{a,b,c}”是一个列表,而不是 哈希值。再次,mea culpa没有提到这一点。
我知道执行此操作的“正常”方式是递归的:处理每个 如果元素是列表,则在列表本身上调用f()。一世 试图“展开”递归以避免分裂嵌套 “{”。如果你在里面工作,你永远不必计算“{” 解析。
一个有趣的其他应用程序将是一个单行的XML解析器(差不多)。
给geekosaur一个勾选标记,指出哪里出错了 为什么我的方法可能是错的。
我想我会尝试解析器方法甚至是jrey的s / {/ [方法。
答案 0 :(得分:5)
你不能让$all
同时成为一个字符串,你在和上迭代匹配一个收集迭代结果的arrayref。 $all
最终会变成字符串"thisARRAY(0xdeadbeef)foryou"
,而@$all
会将其用作包符号名称,几乎肯定没有定义,因此它会自动归档为空列表
此外,{}
已经是HASH
而不是ARRAY
)引用,因此您将SCALAR
引用返回到HASH
引用您显然期望的ARRAY
参考。 {}
在正则表达式中很特殊(foo{1,3}
表示1到3次重复foo
),所以你应该逃避它们。
正确的方法是收集到结果列表中,例如
my @res;
while ($all =~ /\G\{([^{}]*?)\}/sg) {
push @res, f($1);
}
use warnings
和use strict
会告诉你一些错误,如果不是恰当的话。使用它们。总是
答案 1 :(得分:2)
使用解析器。
#! /usr/bin/env perl
use warnings;
use strict;
use Data::Dumper;
use Parse::RecDescent;
my $all = "{this, {is, some, {deeply, nested}, text}, for, you}";
my $p = Parse::RecDescent->new(q[
list: '{' <commit> listitem(s /,/) '}' { $return = $item[3] }
| <error?>
listitem: word | list
word: /\w+/
]);
my $l = $p->list($all);
die "$0: bad list\n" unless defined $l;
$Data::Dumper::Indent = $Data::Dumper::Terse = 1;
print Dumper $l;
输出:
[ 'this', [ 'is', 'some', [ 'deeply', 'nested' ], 'text' ], 'for', 'you' ]
答案 2 :(得分:0)
您的文本格式很容易转换为Perl,之后您可以评估它。
#!/usr/bin/env perl
my $all = "{this, {is, some, {deeply, nested}, text}, for, you}";
$all =~ s/\s*,\s*/','/g;
$all =~ s/'?\{/['/g;
$all =~ s/\}'?/']/g;
my $result = eval $all;
use Data::Dumper;
print Dumper $result;