使用温度转换脚本学习 Perl

467 位读者喜欢这篇文章。
code.org keynote address

Opensource.com

多年来,我自学了多种编程语言,包括 Perl。 我发现的一种学习工具是使用某种语言参考,以避免通过手册中的多个章节来找到一个起点的挫败感。

另一个好的学习技巧是找到一个 Perl 程序,它做的事情与你想要做的类似,然后通过修改它的行为来逐渐修改它,并在遇到困难时使用你的参考。 最终,在你形成了一些你想做什么的想法之后,你就能从头开始了,然后将它翻译成一组编程指令。

几年前,在合作编写 Scribus 手册的过程中,我花了很多时间在 freenode.net 的 Scribus 频道上,与我的德国合作者和其他主要生活在欧洲的人交谈。 你最终会就各种话题进行大量对话,无论你在世界的哪个地方,你都会谈论天气,但当然他们谈论的是摄氏温度,而我体验的是华氏温度。 所以我用 Perl 做了一个小工具来查看 14°C 是多少,或者也许我不用 °F 告诉他们我的天气,而是能够给他们一个 °C 的数字。

让我们用这个来谈谈 Perl。

#!/usr/bin/perl -w
print "\nThis is the program for Fahrenheit to Celsius\n 
and Celsius to Fahrenheit temperature conversion\n\n";
$temp = $ARGV[0];
$f1temp = $temp . "°F";
$ctemp = ($temp - 32)* 5.0/9.0;
$rtemp = sprintf("%.1f", $ctemp);
$c1temp = $rtemp . "°C";
print "$f1temp is $c1temp\n\n";

$ftemp = $temp* 9.0/5.0 + 32;
$rtemp = sprintf("%.1f", $ftemp);
$c2temp = $temp . "°C";
$f2temp = $rtemp . "°F";
print "$c2temp is $f2temp\n\n";

我将它命名为 tempconv.pl,所以首先要指出的是,你用 .pl 扩展名来命名文件,以表明这是一个 Perl 脚本。 接下来,看看第一行。 它以这些字符开头:#! 这有一个名称,shebang,之后它告诉你的计算机在哪里找到解释器,-w 请求有关我在编写此脚本时可能犯的错误的警告。 这一行必须是脚本的第一行。

第二行只是给自己的一个小消息,以确认它在做什么,当然这不仅是输出的一部分,而且当我查看文件时我可以阅读它,所以在这种情况下,它是这个脚本的完整文档。 你反复看到的这个 \n 是为了让打印输出(在本例中是在屏幕上)添加一个新行或回车符。 如果你稍微分解输出,它更容易阅读。 我使用了双引号,它的行为与单引号不同。 例如,单引号内的 \n 会按字面打印;它不会被解释,也不会创建新行。

第三行终于到了我们运行它的目的的核心。 注意所有以 $ 开头的单词或单词片段。 所有变量名都必须以特殊字符开头。 $ 表示标量变量,或者换句话说,具有单个值的变量。 ARGV 是 Perl 使用的特殊变量名,用于引用程序运行时发送给脚本的任何输入。

事实上,我可以输入多个数字,tempconv.pl 45 23 38,在这种情况下,这三个值会创建一个数组 @ARGV,从中我们可以指定 $ARGV[0],这将是 45,或 $ARGV[1] 代表 23,等等。 由于这个脚本的编写方式,无论你包含多少个值都无关紧要,因为它只会使用第一个值。(我们稍后再讨论。)

要转换温度,请输入 tempconv.pl 45 以转换值 45。 ARGV 指的是该输入,45。

接下来,发生了一些有趣的事情。 注意我是如何将 45 °F 的字符串值分配给变量 $f1temp 的(句点是一个连接运算符,将这两个字符串粘合在一起)。 在下一行中,我采用相同的输入并对其执行数学运算。 那么 45 是一个字符串还是一个数字? 显然两者都是。 你应该能够识别出华氏温度转换为摄氏温度的公式 ($temp - 32)*9.0/5.0

剩下的就是打印结果,但我想确保它以一位小数点的浮点数输出,这就是 sprintf 命令的作用。

此脚本的其余部分只是假设 45 是摄氏度并转换为华氏度,因此该脚本的总输出为

This is the program for Fahrenheit to Celsius
 and Celsius to Fahrenheit temperature conversion

45°F is 7.2°C

45°C is 113.0°F

我这样做似乎很奇怪,但实际情况是,我最初制作了两个脚本,一个名为 celsius.pl,另一个名为 fahren.pl,每个脚本只做一次计算。 问题是,过了一段时间后,我忘记了 celsius.pl 是想要一个摄氏值还是在生成一个摄氏值。 我觉得最简单的事情就是将操作结合起来,给出两个答案并保持使用的简单性。 为了进一步简化,我还创建了一个在 Bash 中运行的别名,称为 temp,它不仅节省了键入整个文件名的时间,而且还节省了键入其路径的时间。

一个不太困难的添加是创建一个循环,以便可以输入多个值,并进行串行计算。 主要考虑因素是检测输入了多少个值以避免生成错误。 更重要的是,我还没有看到这种需求。 但让我们在这里提到 Perl 的一个你可能已经注意到的特性,那就是除了第一个之外,每行都以分号结尾。 我应该补充说,每个可执行语句都以分号结尾。 例如,假设我们想根据条件在末尾添加一条可选消息


if ($rtemp > 99) {
	print "Wow! That's hot!\n\n";
}

可执行部分仍然以分号结尾,但 if 条件有它自己的结构,使用大括号来包含如果满足条件将执行的所有行。 通常,这些行会缩进,以便你在阅读脚本时更容易地将它们突出显示。

很容易想象将你在这里看到的内容用于制作各种其他小实用程序来转换重量、距离、排版度量等等,事实上我已经做了很多这样的事情。

标签
Greg Pittman
Greg 是肯塔基州路易斯维尔的一位退休神经科医生,自 20 世纪 60 年代以来一直对计算机和编程有着浓厚的兴趣,最早接触的是 Fortran IV。 当 Linux 和开源软件出现时,它激发了他学习更多知识并最终做出贡献的承诺。 他是 Scribus 团队的成员。

9 条评论

在发布类似文章之前,你可能需要检查你的 Perl 是否是最新的。 当 Perl 5.6 在 2000 年发布时,像那样在 shebang 行上使用 '-w'。 现在,我们在程序中使用“use warnings”来代替。 我们也喜欢鼓励人们包含“use strict”,因为它(除了其他事情之外)强制你声明你的变量。

我一直喜欢 Larry Wall 的一点是他自称的懒惰以及他的幽默感。 从一种极客的方式来说,《Learning Perl》是一本非常有趣的书。
我倾向于“如果它没有坏,就不要修理它”的原则,并且这个脚本在 Fedora 24 附带的 Perl 上继续为我工作。

我同意。 这是我用别名做的一个额外的

$ vi .bashrc
alias jdegrees='perl /path/2/tempconv.pl $1'
$ . .bashrc
$ jdegrees 32

现在,从命令行上的任何地方和任何位置,我都可以运行你的程序。 将别名添加到 .bashrc,刷新 .bashrc,他们学会了更加懒惰 ;-)

回复 作者: Greg P

Perl 的优点之一是有一种以上的方法来做(TIMTOWDI)。 这是你的脚本,只需进行最少的更改即可转换为 Perl 6

print "\n这是将华氏温度转换为摄氏温度的程序\n
以及将摄氏温度转换为华氏温度\n\n";
my $temp = @*ARGS[0];
my $f1temp = $temp ~ "°F";
my $ctemp = ($temp - 32) * 5/9;
my $rtemp = sprintf("%.1f", $ctemp);
my $c1temp = $rtemp ~ "°C";
print "$f1temp is $c1temp\n\n";

my $ftemp = $temp* 9/5 + 32;
$rtemp = sprintf("%.1f", $ftemp);
my $c2temp = $temp ~ "°C";
my $f2temp = $rtemp ~ "°F";
print "$c2temp is $f2temp\n\n";

在仔细审查之前,很高兴看到更多人使用 Perl,所以我希望看到更多这样的例子。请不要太在意我的评论,我只是想提供帮助,希望不会太负面。话虽如此...

您可以使用较新的 Perl 版本,例如 "use v5.18.0;",并用 "say" 语句替换您的 "print" 语句,"say" 语句会自动在字符串或对象后添加换行符。

也建议不要使用系统 Perl,而是使用 "#!/usr/bin/env perl"。

还要考虑您的用例,如果有人尝试在没有任何参数的情况下运行脚本会怎么样?作为参考,您可以查看 James Clark 的博客(位于 http://blog.lazycat.com.au/),他在那里发布了一些 Perl 6 和 Perl 5 脚本,展示了一些最佳实践。

当然,你会遇到错误。如果这些错误很容易理解,我通常不介意,而 "use of uninitialized value..." 就很容易理解。

回复 作者:Tim Van den La… (未验证)

哦,我丝毫没有暗示你的代码无法工作。当然,它是可以的。只是当我在为公众编写代码时,我喜欢确保我使用的是当前的最佳实践。

这是我编写你的程序的方式

#!/usr/bin/perl

use strict;
use warnings;

print "\n这是华氏温度到摄氏温度的转换程序\n" .
"以及摄氏温度到华氏温度的转换程序\n\n";

my $temp = shift;

printf "%s°F is %.1f°C\n\n", $temp, ($temp - 32) * 5 / 9;
printf "%s°C is %.1f°F\n\n", $temp, ($temp * 9 / 5) + 32;

我喜欢你写的代码的简洁性。我当然不是想把自己塑造成 Perl 专家,更像是自己学习了一些东西的人,我知道这很明显。
查阅了网络上的各种参考资料后,似乎其中很多都会吓跑人们。我希望在这里以一种不吓人的方式对一个小程序进行彻底的剖析。

回复 作者:Dave Cross (未验证)

也在看这个,并想出了一个和你非常相似的答案 Dave!

在你的答案的基础上更进一步(或者至少是我自己的版本),你可以很容易地使用以下方法循环它

#! /usr/bin/env perl

use strict;
use warnings;

print "\n这是华氏温度到摄氏温度的转换程序\n"
. "以及摄氏温度到华氏温度的转换程序\n\n";

while ( my $temp = shift ) {
my $ctemp = ($temp - 32) * 5.0/9.0;
my $ftemp = ($temp * 9.0/5.0) + 32;

printf "%.1f°F is %.1f°C\n\n", $temp, $ctemp;
printf "%.1f°C is %.1f°F\n\n", $temp, $ftemp;
}

这个版本允许你传递多个数字,它会转换所有这些数字!

回复 作者:Dave Cross (未验证)

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.