Perl:将作为参数传递给变量的变量修改为子例程
我需要修改例程中的变量,以便在离开例程后保留更改。这里有一个例子:Perl:将作为参数传递给变量的变量修改为子例程
$text = "hello";
&convert_to_uppercase($text);
print $text;
我想在屏幕上看到“你好”,而不是“你好”。
的常规是:
sub convert_to_uppercase($text){
<something like $text = uc($text);>
}
我知道如何做到这一点在PHP,但似乎未更改参数的方法相同。而且,我一直在寻找,我找不到具体的答案。
我会很感激任何帮助。谢谢!
你真的调用Perl子程序时不应该使用&符号&
。仅在将代码视为数据项时才有必要,例如在参考时,如\&convert_to_uppercase
。在Perl 5的版本4中,在调用中使用它并不是必需的,它会执行一些你可能不想要的东西。
子程序修改它们的参数是不常见的,但@_
的元素是实际参数的别名,因此您可以通过修改该数组来做到这一点。
如果你写你的子程序这样
sub convert_to_uppercase {
$_[0] = uc $_[0];
}
然后它会做什么你问。但通常最好是返回修改后的值,以便决定是否覆盖原始值可以由调用代码进行。举例来说,如果我有
sub upper_case {
uc shift;
}
那么它可以被称为要么作为
my $text = "hello";
$text = upper_case($text);
print $text;
它确实如你需要,并修改$text
;或作为
my $text = "hello";
print upper_case($text);
其中$text
保持不变,但返回更改的值。
太棒了!还有一件事:是否有必要声明例程签名?我看到你做** sub convert_to_uppercase {} **而不是** sub convert_to_uppercase($ text){} **,但是当你调用它时,你会执行** convert_to_uppercase($ text)**。 另一件事,我用**&**,因为我不知道我不应该,我对Perl真的很陌生。我正在做的是用户输入的验证,所以我想大写用户的输入(我会稍后再检查它),并返回1或0,如果有效或不是,那就是为什么我不这样做使用返回来做到这一点。 你真的很有帮助,非常感谢! – gonfer 2014-10-16 23:22:11
@gonfer,no。自从Perl 5.20(几个月前发布)以来,子签名才被添加为核心Perl特性,并且仅在实验中使用。 (虽然签名的几种实现方式可用作不同级别稳定性的扩展模块。) – tobyink 2014-10-17 09:37:57
传递一个参考和修改子程序内的原始变量将这样来完成:
$text = 'hello';
convert_to_uppercase(\$text); #notice the \ before $text
print $text;
sub convert_to_uppercase { #perl doesn't specify arguments here
### arguments will be in @_, so @_ is now a list like ('hello')
my $ref = shift; #$ref is NOT 'hello'. it's '$text'
### add some output so you can see what's going on:
print 'Variable $ref is: ', $ref, " \n"; #will print some hex number like SCALAR(0xad1d2)
print 'Variable ${$ref} is: ', ${$ref}, " \n"; #will print 'hello'
# Now do what this function is supposed to do:
${$ref} = uc ${$ref}; #it's modifying the original variable, not a copy of it
}
另一种方法是给子程序外部创建的子程序内的返回值并修改变量:
$text = 'hello';
$text = convert_to_uppercase($text); #there's no \ this time
print $text;
sub convert_to_uppercase {
# @_ contains 'hello'
my $input = shift; #$input is 'hello'
return uc $input; #returns 'HELLO'
}
但是convert_to_uppercase例程似乎是多余的,因为这就是uc所做的。跳过这一切,只是这样做:
$text = 'hello';
$text = uc $text;
你好,你清除了我所有的疑惑!当我回复其他人时,我正在验证用户输入的密钥。我想将它大写并验证它,并将其保留为大写字母以备将来检查。如果它是有效的,我会返回1,否则返回0.一个简单的** uc **会更容易,但我想在一个例程中完成所有这些。非常感谢你。我很高兴在这里回复的质量和速度。 – gonfer 2014-10-16 23:28:09
现在我再读一遍:再次修改@_,变量在例程外被修改,但是在调用子程序时是否需要传递变量?这样,$ ref就是对变量的实际引用,并且您可以用{}去引用它。仅当您使用\来传递参数时,才会使用{}。谢谢! – gonfer 2014-10-16 23:33:15
值得一提的是,你可以使用'convert_to_uppercase($ text);'(在子例程参数前面没有“\”)而不是'convert_to_uppercase(\ $ text);''shift'前加'\':'my $ ref = \ shift;' – Omar 2017-01-25 14:35:25
这个问题可能会有所帮助:http://stackoverflow.com/questions/24063638/if-perl-is-call-by-reference-why-does-this-发生 – AntonH 2014-10-16 22:21:29
非常感谢!我的新问题是:为什么($ x1,$ y1)= @_;?如果我这样做,它会是相同的:** $ x1 = $ _ [0]; $ y1 = $ _ [1]; **?请考虑我对Perl真的很陌生,并感谢您的耐心等待! – gonfer 2014-10-16 23:14:37
是的。 '($ x1,$ y1)= @_;'是一个快捷方式。 – AntonH 2014-10-16 23:27:12