在这个perl代码中,$\在哪里被修改?
以下perl代码以PerlCritic(按Activestate)生成警告: 生成的警告是: 不要在列表函数中修改$ 我不理解这个警告,因为我不认为我在修改$\ux,尽管我想我必须这样做。在这个perl代码中,$\在哪里被修改?,perl,natural-sort,perl-critic,Perl,Natural Sort,Perl Critic,以下perl代码以PerlCritic(按Activestate)生成警告: 生成的警告是: 不要在列表函数中修改$ 我不理解这个警告,因为我不认为我在修改$\ux,尽管我想我必须这样做。 有人能给我解释一下吗?你在grep中做一个替换(即s//),它修改$,即列表被格雷格化。你的grep都在修改$\ucode>,因为你正在使用s/。例如,这: grep {s/(^|\D)0+(\d)/$1$2/g,1} 与此相同: grep { $_ =~ s/(^|\D)0+(\d)/$1$2/g; 1
有人能给我解释一下吗?你在grep中做一个替换(即
s//
),它修改$,即列表被格雷格化。你的grep
都在修改$\ucode>,因为你正在使用s/
。例如,这:
grep {s/(^|\D)0+(\d)/$1$2/g,1}
与此相同:
grep { $_ =~ s/(^|\D)0+(\d)/$1$2/g; 1 }
我认为您最好使用map
,因为您没有使用grep
s过滤任何内容,您只是使用grep
作为迭代器:
sub natural_sort {
my $t;
return map { ($t = $_) =~ s/(^|\D)0+(\d)/$1$2/g; $t }
sort
map { ($t = $_) =~ s/(\d+)/sprintf"%06.6d",$1/ge; $t }
@_;
}
这应该做同样的事情,让批评家保持沉默。如果您想要一些比普通的map
更好的列表运算符,您可能需要了解一下这一情况和其他情况的解释如下:
下面是Perl将要使用的地方
假设$u,即使您不使用它:
- 以下功能:
防抱死制动系统,警报,嘎嘎声,嘎嘎声,嘎嘎声,嘎嘎声,嘎嘎声,嘎嘎声,
cos,defined,eval,exp,glob,hex,
int,lc,lcfirst,length,log,lstat,
mkdir、oct、ord、pos、打印、,
quotemeta、readlink、readpipe、ref、,
require,reverse(在标量上下文中)
仅),rmdir,sin,split(在其上)
第二个参数),sqrt,统计,研究,
uc,ucfirst,取消链接,解包
- 除了-t(默认为STDIN)之外的所有文件测试(-f,-d)。
见-X
- 模式匹配操作m//、s//和tr//(也称为y//)在
不带=~运算符使用
- 如果未指定其他变量,则foreach循环中的默认迭代器变量
供应
- grep()和map()函数中的隐式迭代器变量
- 给定()的隐式变量
- 当操作的结果失败时放置输入记录的默认位置
作为唯一的测试工具进行测试
一段时间测试的标准。在a之外
在测试期间,这不会发生
其他答案遗漏的非常重要的部分是这条线
grep {s/(\d+)/sprintf"%06.6d",$1/ge,1} @_;
实际上是修改传递到函数中的参数,而不是它们的副本
grep
是一个过滤命令,代码块内的$\u
中的值是@
中一个值的别名@
又包含传递给函数的参数的别名,因此当s///
运算符执行其替换时,会对原始参数进行更改。如下例所示:
sub test {grep {s/a/b/g; 1} @_}
my @array = qw(cat bat sat);
my @new = test @array;
say "@new"; # prints "cbt bbt sbt" as it should
say "@array"; # prints "cbt bbt sbt" as well, which is probably an error
您正在寻找的行为(将修改列表副本的函数应用于列表副本)已封装为许多模块中的apply
函数。我的模块包含这样一个实现<代码>应用
也很容易自己编写:
sub apply (&@) {
my ($sub, @ret) = @_;
$sub->() for @ret;
wantarray ? @ret : pop @ret
}
这样,您的代码可以重写为:
sub natural_sort {
apply {s/(^|\D)0+(\d)/$1$2/g} sort apply {s/(\d+)/sprintf"%06.6d",$1/ge} @_
}
如果重复替换的目标是在应用临时修改的情况下执行一种原始数据,那么您应该研究一种称为的Perl惯用法,它是实现该目标的更有效的方法。许多人正确地回答了s
操作符正在修改$\ucode>,然而,在即将发布的Perl 5.14.0中,s
操作符(即s///r
)将使用新的r
标志,它将返回修改后的元素,而不是就地修改。阅读更多信息。您可以使用安装此新版本
编辑:Perl 5.14现在可用
以下是mu建议的功能(使用map
),但使用此功能:
use 5.14.0;
sub natural_sort {
return map { s/(^|\D)0+(\d)/$1$2/gr }
sort
map { s/(\d+)/sprintf"%06.6d",$1/gre }
@_;
}
我将研究一下这个习惯用法,但是考虑到我的数据,修改参数是可以接受的。@Craig=>如果是非故意的,修改参数是永远不能接受的。如果几个月后,您需要对常量数组或将再次使用的数组使用排序,该怎么办?明白您的意思,但这不会发生,我说过我会看看这个习惯用法
use 5.14.0;
sub natural_sort {
return map { s/(^|\D)0+(\d)/$1$2/gr }
sort
map { s/(\d+)/sprintf"%06.6d",$1/gre }
@_;
}