循环while(@ARGV>0)
不分配给$_
正则表达式匹配已完成,因此没有任何内容匹配,代码转到else
. Also, @ARGV
永远不会被清空,因此代码处于无限循环中。
其余代码在语法上是正确的,但必须重写,因为它会迭代输入中的单词,而编写正则表达式来处理整个输入。对于该正则表达式,处理需要依次采用每个参数,或者需要将命令行组装成字符串。
下面进一步发布了对问题中代码的进一步评论。
让我提供一种不同的方法
use warnings;
use strict;
use feature 'say';
use Scalar::Util qw(looks_like_number);
my ($n1, $op, $n2) = @ARGV;
my $re_oper = qr{^(?:\+|-|\*|/)$}; #/
usage() if @ARGV != 3
or not looks_like_number($n1) or not looks_like_number($n2)
or $op !~ $re_oper;
my %calculate = (
'+' => sub { return $_[0] + $_[1] },
'-' => sub { return $_[0] - $_[1] },
'*' => sub { return $_[0] * $_[1] },
'/' => sub {
die "Can't divide by zero" if $_[1] == 0;
return $_[0] / $_[1]
},
);
say $calculate{$op}->($n1, $n2);
sub usage {
say STDERR
"Usage: $0 number operator number\n",
"The \"operator\" is one of +,-,\\*,/\n",
"Note that multiplication (*) must be escaped at command line";
exit;
}
使用复制参数并检查错误looks_like_number
from 标量::实用程序 https://perldoc.perl.org/5.8.9/Scalar/Util.html和一个正则表达式。我使用以下方法准备正则表达式模式qr操作员 http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators因此单独指定,使测试、维护和扩展更容易。
然后我们定义一个以匿名子例程作为值的哈希(它们是代码参考, 参见项目4. in 在 perlref 中进行引用 https://perldoc.perl.org/perlref.html#Making-References),通常称为调度表 https://en.wikipedia.org/wiki/Dispatch_table#Perl_implementation。因此不需要级联if-elsif
系列:对于给定的键(运算符),相应的值被取消引用并且该子例程运行。
为了简洁起见,在一个语句中检查参数,但最好逐一检查,以便能够向用户报告所发生的确切错误(并引用导致该错误的输入)。
有关已发布代码的更多细节
操作员捕获的模式需要使用进行测试string比较,做了什么eq
运算符,不与==
。看看这些在佩洛普 https://perldoc.perl.org/perlop.html#Equality-Operators.
So if ($2 eq '+')
etc
默认情况下,正则表达式匹配是针对$_多变的 https://perldoc.perl.org/perlvar.html#General-Variables,Perl 中许多事物的默认值。所以没必要写if ($_ =~ /.../)
只是if (/.../)
。阅读证明(隐式)使用的合理性的理由要清楚得多$_
正则表达式模式\d
匹配所有类型的数字,包括 Unicode。更好的利用[0-9]
图案\s
允许one“空白”字符。如果将命令行参数组合成一个字符串$input = join ' ', @ARGV;
(所以要使用正则表达式)那么就可以了。但留出更多空间仍然更安全\s+
.
The .
在正则表达式中匹配任何one特点。这限制了脚本未来可能的扩展,例如权力提升**
(ETC)。考虑允许数字之间存在任何字符,这是可行的,因为它们在命令行上由空格分隔。
用于数字的模式仅匹配正整数(同时如果前面有负号,则意外地允许第一个整数为负数)。上面的代码通过使用来解决这个问题looks_like_number
,它利用 Perl 的所有功能来识别数字。
问题的原始版本 had while (<>)
for 循环,答案由此开始:
The “钻石”运算符(<>) https://perldoc.perl.org/perlop.html#I/O-Operators从命令行提交的文件中读取
输入来自<>
来自标准输入,或来自命令行上列出的每个文件。
所以你的输入5 + 2
被视为文件名5
and +
and 2
,并且此类文件不存在。
该运算符更加复杂,可以在文档中阅读有关内容。
可以在以下位置访问命令行参数@ARGV https://perldoc.perl.org/perlvar.html#ARGV,所以最简单的解决方案是替换while (<>)
with foreach (@ARGV)
然后逐项处理。