将散列传递给子例程会在perl中出错 [英] Pass hash to subroutine comes to error in perl

查看:134
本文介绍了将散列传递给子例程会在perl中出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码如下,

  my%srvs =(
serv_1 => {
agents =>'agent_path',
...
...
},
serv_2 => {
<与上面相同>
},
serv_3 => {
...
........
........
serv_8 => ; {
...
},
);

switch($ option){
case 1 {printOption 1 selected。\\\
; &安培;主; }
案例2 {打印选择了选项2。\\\
;停止(\%srvs); }
案例3 {print选择了选项3。\\\
;启动(\%srvs); }
else {print选项无效。\\\
;退出0; }
}

sub stop {
my $ servs = @_;

foreach我的$ s_name(排序键%{$ servs}){
print$ s_name \\\
;
$ b my $ ssh = Net :: OpenSSH-> new(< user_id> \ @ $ s_name,timeout => 30);
$ ssh->错误,并死亡无法连接$ s_name --->。 $ ssh->错误并打印\\\
;

$ ssh-> pipe_in(perl /<path> /<script_name>.pl stop all)或死掉Unable to run command.\\\
;
}

}

我试图做的是get服务器名称是%srvs的关键字,它是(serv_1,serv2等)



当我运行代码时,我收到下面的错误消息,


不能使用字符串(1)作为HASH ref,而使用strict refs时使用
.pl行260, <>第1行


我也尝试使用不同的方法,即从case控制语句中调用数组, b
$ b

  ---- 
----
案例2 {print选择了选项2。\\\
;我的@s =排序键%srvs;停止( @ S); }
---
---
子停止{

我@servs = @_;

foreach my $ s_name(@serv){
print$ s_name \\\
;
$ b my $ ssh = Net :: OpenSSH-> new(< id_server> \ @ $ s_name,timeout => 30);
$ ssh->错误,并死亡无法连接$ s_name --->。 $ ssh->错误并打印\\\
;

$ ssh-> pipe_in(< path_name>< script_name> .pl stop all)或死亡Unable to run command.\\\
;






这段代码可以被处理,但是它列出了所有的服务器名称(这是%srvs的所有键),我不能使用foreach来划分列表。



需要帮助,因为与传递方法相当混淆。

解决方案

赋值位于子站中的标量上下文中该行

  my $ servs = @_; 

所以 $ servs 收到元素的数量 @_ ,即代码中的 1 。然后,尝试使用%{$ servs} 取消引用 1 会引发错误。



将其更改为 my($ servs)= @_; 其中()结果在 = < $ c

几个注释 p>


  • 服务器散列可能主要通过引用来使用。那么为什么不使用hashref, my $ serv = {...}


  • 引用标量的原因,如$ option; switch($ option)


  • & 在一个子前面是相当特殊的;您大多可能需要 main()而不是& main


  • 第二个代码示例包含 stop(@ s); ,其中插入了 @s 内部。所以子接收一个字符串:它们之间有空格的数组元素。你需要 stop(@s)




使用切换模块。这是一个相当不重要的源过滤器;当然还有其他方法可以做你需要的。 功能开关也是试验性的。请参阅在perlsyn中切换语句






 当然, my @args = @_; 的用途相同。然后适当地处理 @args



检索第一个参数的一种常见方法也是

  sub fun {
my $ first_arg = shift; #与:shift @_相同;
...
}

shift 从它的参数(数组)前面移除一个元素,并返回它;默认情况下它作用于 @_ ,因此您不必编写它。

这在面向对象的代码中经常出现,它使对象脱离 @_ ,这样<$然后可以更轻松地处理c $ c> @_ 。但是为了方便起见,当 @_ 有单个参数时也经常使用它。


My code as below,

my %srvs = (
    serv_1 => {
         agents => 'agent_path',
         ...
         ...
    },
    serv_2 => {
         <same like above>
    },
    serv_3 => {
          ...
    ........
    ........
    serv_8 => {
            ...
    },
);

        switch ("$option") {
                case 1  { print "Option 1 selected. \n"; &main; }
                case 2  { print "Option 2 selected. \n"; stop(\%srvs); }
                case 3  { print "Option 3 selected. \n"; start(\%srvs); }
                else    { print "Option are not valid. \n"; exit 0; }
        }

sub stop {
        my $servs = @_;

        foreach my $s_name (sort keys %{$servs}) {
                print "$s_name \n";             

                my $ssh = Net::OpenSSH->new("<user_id>\@$s_name", timeout=>30);
                $ssh->error and die "Unable to connect $s_name  --->  " . $ssh->error and print "\n";

                $ssh->pipe_in("perl /<path>/<script_name>.pl stop all") or die "Unable to run command.\n";
        }

}

What I try to do is get a server name which is the keys of %srvs, which is (serv_1, serv2, etc.)

When I run the code, I received below error,

Can't use string ("1") as a HASH ref while "strict refs" in use at .pl line 260, <> line 1.

I also try different method which is call as array from the case control statement,

----
----
case 2  { print "Option 2 selected. \n"; my @s = sort keys %srvs; stop("@s"); }
---
---
sub stop {

        my @servs = @_;

        foreach my $s_name (@serv) {
                print "$s_name \n";             

                my $ssh = Net::OpenSSH->new("<id_server>\@$s_name", timeout=>30);
                $ssh->error and die "Unable to connect $s_name  --->  " . $ssh->error and print "\n";

                $ssh->pipe_in("<path_name> <script_name>.pl stop all") or die "Unable to run command.\n";
        }
}

This code can be process, however it list all the server name (which is all the keys of %srvs) in single flat line, I cannot divide the list using foreach.

Need assist since quite confuse with the passing method.

解决方案

The assignment is in the scalar context in your sub stop on the line

my $servs = @_;

so $servs receives the number of elements of @_, that is 1 in your code. Then the attempt to dereference that 1 with %{$servs} draws the error.

Change it to my ($servs) = @_; where the () results in the list context for =

A few comments.

  • The hash with servers is likely to be used mostly via its reference. Then why not use a hashref, my $serv = { ... }

  • There is never a reason to quote a scalar, like "$option"; just switch($option)

  • The & in front of a sub is quite special; you mostly likely need main() instead of &main

  • Second code sample has stop("@s");, whereby @s is interpolated inside "". So the sub receives a single string: array elements with spaces between them. You need stop(@s)

You seem to be using Switch module. It is a rather non-trivial source filter; surely there are other ways to do what you need. The feature switch is experimental, too. See Switch Statements in perlsyn


  The my @args = @_; serves the same purpose of course. Then process @args suitably.

A commonly seen way to retrieve the first argument is also

sub fun {
    my $first_arg = shift;  # same as: shift @_;
    ...
}

The shift removes an element from the front of its argument (array), and returns it; by default it acts on @_ which you thus don't have to write.

This is often seen in object-oriented code, to get the object off of @_ so that @_ can then be worked with more easily. But it is also often used when @_ has a single argument, for convenience.

这篇关于将散列传递给子例程会在perl中出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆