在perl中将列表上下文结果转换为一行中的数组?

par*_*par 10 perl

我在perl中编写了这段代码:

shift( @interfaces = qx'ifconfig -s' );
Run Code Online (Sandbox Code Playgroud)

并得到这个错误:

Type of arg 1 to shift must be array (not list assignment)
Run Code Online (Sandbox Code Playgroud)

当我这样写的时候:

@interfaces = qx'ifconfig -s';
shift @interfaces;
Run Code Online (Sandbox Code Playgroud)

它做我想要的,即将ifconfig命令的输出作为一个行数组并删除数组中的第一个元素(这是一个标题,而不是一个实际的接口).

我个人的偏好是把它写成一个班轮.在我看来,第一个例子中的括号应该导致赋值被完全解析,因此允许转换将@interfaces看作一个数组,但显然perl认为它是一个"列表赋值".

对于perl大师来说,这肯定是一个简单的问题,但我用Google搜索并用谷歌搜索并没有找到启示.

如果有人愿意提供具体的语义来完成我想要的一行,我将不胜感激.如果你也请花时间解释为什么我的第一个版本不起作用我会永远感激(教一个人钓鱼等等).

预先感谢您的帮助.

Eri*_*rom 13

如您所见,shift需要一个文字数组,而不是赋值的结果.这是因为当perl解析shift @interfaces它实际上是将它重写为类似的东西&CORE::shift(\@interfaces),你不能参考赋值并获得数组引用.

你可以将它分成两行,如你所发现的那样,你可以在一个包围的解引用中隐藏任务,就像暴徒所显示的那样,或者你可以简单地扔掉第一个值:

(undef, @interfaces) = qx'ifconfig -s';
Run Code Online (Sandbox Code Playgroud)

undef 在左值位置是占位符,表示您不需要的值.

(解析shift在perl 5.14+ 中有所改变,但上面的论点仍然成立)


您可能不应该使用的更多方法,仅通过增加长度来订购:)

my @interfaces = sub {shift; @_}->(qx'ifconfig -s');

my @interfaces = sub {@_[1..$#_]}->(qx'ifconfig -s');

my @interfaces = map {@$_[1..$#$_]} [qx'ifconfig -s'];

my @interfaces = map {shift @$_; @$_} [qx'ifconfig -s'];

our @interfaces; shift @{*interfaces = [qx'ifconfig -s']};

my @interfaces = sub {*_ = [qx'ifconfig -s']; shift; @_}->();
Run Code Online (Sandbox Code Playgroud)


mob*_*mob 7

shift @{EXPR} 是有效的语法,所以

shift @{$interfaces = [qx'ifconfig -s']}
Run Code Online (Sandbox Code Playgroud)

将为您提供一个删除了第一个元素的数组引用.

我从diagnostics输出中发现了关于shift从列表赋值调用的内容:

$ perl -Mdiagnostics -e 'print shift(@a = (2,3,4))'
Run Code Online (Sandbox Code Playgroud)
Type of arg 1 to shift must be array (not list assignment) at -e line 1, at end of line
 Execution of -e aborted due to compilation errors (#1)
    (F) This function requires the argument in that position to be of a
    certain type.  Arrays must be @NAME or @{EXPR}.  Hashes must be
    %NAME or %{EXPR}.  No implicit dereferencing is allowed--use the
    {EXPR} forms as an explicit dereference.  See perlref.

Perl对任何用户定义的子例程或使用\@\%字符原型化的内置函数强制执行此行为.原型是解释器的线索,Perl应该将数组或散列函数参数视为数组或散列类型,而不是尝试将列表展开为多个参数.

考虑它的一种方法(虽然我不确定这对于内置函数是否准确)是Perl会从函数调用的参数列表中读取数组或哈希变量,但实际上是将对该变量的引用传递给原型功能.因此解释器需要在参数列表中标识数组或散列,并且它需要能够获得对该数组或散列的引用.Perl没有或不能(在这里挥手)用列表赋值表达式做到这一点 - 注意结果

\(@a = (1,2,3))
Run Code Online (Sandbox Code Playgroud)

是对标量的3个引用的列表,而不是对包含3个标量的列表的引用.

您可以使用以下prototype函数查看大多数Perl内置函数的原型(如果有):

$ perl -e 'print prototype("CORE::shift")'      ===>   \@
$ perl -e 'print prototype("CORE::each")'       ===>   \%
$ perl -e 'print prototype("CORE::push")'       ===>   \@@
Run Code Online (Sandbox Code Playgroud)