无法读取子内的公共标量
Perl代码如下:问题是我无法在子tweak_server{} ....
my $key;
my %hash = ( flintstones => [ "C:/Users1/f1.xml", "C:/Users1/f2.xml" ],
jetsons => [ "C:/Users2/f1.xml" ],
simpsons => [ "C:/Users3/f1.xml", "C:/Users3/f1.xml", "C:/Users3/f1.xml" ], );
foreach $key (keys%hash){
if (scalar@{$hash{$key}}>1){
foreach my $path (@{$hash{$key}}){
my $filehandle;
open($filehandle, "+<$path") or die "cannot open out file out_file:$!";
my $roots = { TAG => 1 };
my $handlers = { 'ROOT/TAG' => \&tweak_server,
};
my $twig = new XML::Twig(TwigRoots => $roots,
TwigHandlers => $handlers,
twig_print_outside_roots => \*$filehandle);
$twig->parsefile($path);
say $key;#could read key
sub tweak_server {
my ($twig, $root) = @_;
my $tag2=$root->first_child_text('TAG2');
say $key;# could not read
if ($tag2=~/$key/){
#BLABLA
}
$twig->flush( $filehandle, pretty_print => 'indented');
}
}
}
}
中读取$key,正如我所说,$key可以在子外部读取,但不能在内部读取..出现错误:使用未初始化的值$key
,然后我尝试了一个简单的情况,就像
my $a="aaa";
open( $filehandle, "+<$path") or die "cannot open out file out_file:$!";
my $roots = { TAG => 1 };
my $handlers = { 'ROOT/TAG' => \&tweak_server,
};
my $twig = new XML::Twig(TwigRoots => $roots,
TwigHandlers => $handlers,
twig_print_outside_roots => \*$filehandle
);
$twig->parsefile($path);
sub tweak_server {
say $a;
my ($twig, $root) = @_;
my $tags=$root->first_child_text('TAG2');
my $str="204B";
if ($tag2=~m/$str/){
foreach my $b(1...6){
say $a; }
}
$twig->flush( $filehandle, pretty_print => 'indented');
}
在这段代码中一样,$a可以被读取...... 我花了一天的时间,但仍然无法修复它......现在疯了 预先感谢!
the perl code is like followed : the problem is that I can not read $key inside sub tweak_server{} ....
my $key;
my %hash = ( flintstones => [ "C:/Users1/f1.xml", "C:/Users1/f2.xml" ],
jetsons => [ "C:/Users2/f1.xml" ],
simpsons => [ "C:/Users3/f1.xml", "C:/Users3/f1.xml", "C:/Users3/f1.xml" ], );
foreach $key (keys%hash){
if (scalar@{$hash{$key}}>1){
foreach my $path (@{$hash{$key}}){
my $filehandle;
open($filehandle, "+<$path") or die "cannot open out file out_file:$!";
my $roots = { TAG => 1 };
my $handlers = { 'ROOT/TAG' => \&tweak_server,
};
my $twig = new XML::Twig(TwigRoots => $roots,
TwigHandlers => $handlers,
twig_print_outside_roots => \*$filehandle);
$twig->parsefile($path);
say $key;#could read key
sub tweak_server {
my ($twig, $root) = @_;
my $tag2=$root->first_child_text('TAG2');
say $key;# could not read
if ($tag2=~/$key/){
#BLABLA
}
$twig->flush( $filehandle, pretty_print => 'indented');
}
}
}
}
as i state, the $key can be read outside the sub, but not inside..the error appeared:Use of uninitialized value $key
and then i tried a simple situation, just like
my $a="aaa";
open( $filehandle, "+<$path") or die "cannot open out file out_file:$!";
my $roots = { TAG => 1 };
my $handlers = { 'ROOT/TAG' => \&tweak_server,
};
my $twig = new XML::Twig(TwigRoots => $roots,
TwigHandlers => $handlers,
twig_print_outside_roots => \*$filehandle
);
$twig->parsefile($path);
sub tweak_server {
say $a;
my ($twig, $root) = @_;
my $tags=$root->first_child_text('TAG2');
my $str="204B";
if ($tag2=~m/$str/){
foreach my $b(1...6){
say $a; }
}
$twig->flush( $filehandle, pretty_print => 'indented');
}
in this code, the $a can be read....
i spent one day on this, but still can't fix it...crazy now
thank in advance!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您在
for
循环之外声明$key
。然后,在 for 循环内,定义一个在$key
上结束的子例程。作为一般规则,在最小的适用范围内声明变量。例如:
或者
为什么要在
for
循环体中定义subtweak_server
?在我看来,你想要做的是为每次迭代定义一个新的匿名子。首先,一个简短的示例来复制您所观察到的内容:
现在,修复:
这样,我们在每次迭代时定义一个新的匿名函数,并且每个新的子函数都会关闭循环变量的每个值。
就您的代码而言,您应该将命名的 sub 替换为
或者,更好的是,正如 @mirod 观察到的那样,将
$key
传递给tweak_server
:并且,在循环,
You are declaring
$key
outside of thefor
loop. Then, inside the for loop, you define a subroutine that closes on$key
.As a general rule, declare variables in the smallest applicable scope. For example:
or
Why are you defining
sub tweak_server
in the body of thefor
loop? It seems to me, what you want to do is to define a new anonymous sub for each iterationn.First, a short example that replicates what you are observing:
Now, the fix:
This way, we define a new anonymous function at each iteration and each new sub closes over each value of the loop variable.
In terms of your code, you should then replace the named sub with
Or, even better, as @mirod observes, pass
$key
totweak_server
:And, in the body of the loop,
简短版本:如果您在另一个子程序内部或循环内部有一个命名子程序声明(
sub foo { ... }
),那么您可能做错了什么,您可能需要一个匿名子程序。这里就是这种情况。基本上与如果 sub 引用其自身之外的任何词法 (
my
) 变量相同,则在执行
sub
时(即在编译时)将捕获它们与命名的潜艇。一个常见的错误是这样做不起作用,因为
my $x
被多次调用来创建多个变量,但inner
仅捕获编译时存在的变量。 (幸运的是,它会发出警告。)乍一看,您的代码只有一个名为
$key
的变量,因此在编译时捕获它应该没有问题。但他们的外表是骗人的。由于 foreach 的别名功能,迭代器变量根本不是循环外部的变量。在您的情况下,您希望
子程序在运行时捕获
$x
,这是通过使用匿名子程序来完成的。修复:
您还可以使用匿名包装器将变量作为参数传递给命名子。
Short version: If you have a named sub declariation (
sub foo { ... }
) inside of another sub or inside of a loop, you're probably doing something wrong, you probably want an anonymous sub. This is the case here.is basically the same as
If a sub refers to any lexical (
my
) variables outside of itself, they will be captured when thesub
is executed, which is at compile-time with named subs. A common mistake is to doThat doesn't work because
my $x
is called multiple times to create multiple variables, butinner
only captures the one that existed at compile time. (Fortunately, it warns.)At first glance, your code only has one variable named
$key
, so there should be no problem capturing it at compile time. But they looks are deceiving. Due to foreach's aliasing feature, the iterator variable is not the variable it was outside the loop at all.In your case, you had
You want the sub to capture
$x
at run-time, and that's done by using an anonymous sub.Fix:
You could also use an anonymous wrapper that passes the variables as arguments to a named sub.