加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl 5.10后的新特征 given-when介绍

发布时间:2020-12-16 00:42:57 所属栏目:大数据 来源:网络整理
导读:given 语句 Perl 中的 given-when 控制结构能够根据 given 的参数,执行某个条件对应的语句块,其与 C 语言中的 switch 语句类似。只不过更具有 Perl 的色彩。看看下面的例子,其从命令行中取出第一个参数, $ARGV[0] ,然后依次走一遍 when 条件判断,看是

given语句

Perl中的given-when控制结构能够根据given的参数,执行某个条件对应的语句块,其与C语言中的switch语句类似。只不过更具有Perl的色彩。看看下面的例子,其从命令行中取出第一个参数,$ARGV[0],然后依次走一遍when条件判断,看是否找到了Fred。每个when语句对应不同的处理方式,判断的条件从最宽松的开始测试:

1
2
3
4
5
6
7

use 5.010;
given( $ARGV[0] ) {
? ? when( /fred/i ) { say 'Name has fred in it' }
? ? when( /^Fred/ ) { say 'Name starts with Fred' }
? ? when( 'Fred' ?) { say 'Name is Fred' }
? ? default ? ? ? ? { say "I don't see a Fred" }
? ? }

--given会将参数化为$_,每个when条件都尝试用智能匹配对$_进行测试,实际上可以写成如下形式,这就清除多了:

1
2
3
4
5
6
7

use 5.010;
given( $ARGV[0] ) {
? ? when( $_ ~~ /fred/i ) { say 'Name has fred in it' }
? ? when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred' }
? ? when( $_ ~~ 'Fred' ?) { say 'Name is Fred' }
? ? default ? ? ? ? ? ? ? { say "I don't see a Fred" }
? ? }

--如果$_不能满足任何when条件,perl就会执行default语句块。下面为运行结果:
$ perl5.10.0 switch.pl Fred
Name has fred in it
$ perl5.10.0 switch.pl Frederick
Name has fred in it
$ perl5.10.0 switch.pl Barney
I don't see a Fred
$ perl5.10.0 switch.pl Alfred
Name has fred in it

看到这里你也许会说,Perl中的if-elsif-else语句不是一样可以完成这个例子吗,为什么还要用given-when语句呢,它还有存在的必要吗?实际上他们两个语句最大的不同在于given-when可以在满足某个条件的基础上,继续测试其他的条件,但if-elsif-else一旦满足了某个条件,就只能执行对应的那个语句块。实际上前面的例子可以写成如下的方式:

1
2
3
4
5
6
7

use 5.010;
given( $ARGV[0] ) {
? ? when( $_ ~~ /fred/i ) { say 'Name has fred in it'; break }
? ? when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; break }
? ? when( $_ ~~ 'Fred' ?) { say 'Name is Fred'; break }
? ? default ? ? ? ? ? ? ? { say "I don't see a Fred"; break }
? ? }

--按照这种写法,因为第一条测试语句如果传来的参数匹配/fred/i,后面的所有语句就没有机会执行了,这时候就会直接跳出控制结构。如果在when语句块的末尾使用continuePerl就会尝试执行后续的when语句了,这也是if-elsif-else语句块力不能及的地方。当另一个when的条件满足时,会执行对应语句块。在每个when语句块的末尾写上continue,就意味着所有的条件判断都会执行:

1
2
3
4
5
6
7

use 5.010;
given( $ARGV[0] ) {
? ? when( $_ ~~ /fred/i ) { say 'Name has fred in it'; continue }
? ? when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; continue }
? ? when( $_ ~~ 'Fred' ?) { say 'Name is Fred'; continue } #
注意!
? ? default ? ? ? ? ? ? ? { say "I don't see a Fred" }
? ? }

--实际上这样写是有问题的,这里的default总是会运行
$ perl5.10.0 switch.pl Alfred
Name has fred in it
I don't see a Fred

--default块相当于一个测试条件永远为真的when语句。如果在default之前的when语句使用了continuePer就会继续执行default语句。因此可以说default就是一个特殊的when

1
2
3
4
5
6
7

use 5.010;
given( $ARGV[0] ) {
? ? when( $_ ~~ /fred/i ) { say 'Name has fred in it'; continue }
? ? when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; continue }
? ? when( $_ ~~ 'Fred' ?) { say 'Name is Fred'; continue } #
注意!
? ? when( 1 == 1 ? ? ? ?) { say "I don't see a Fred" } #
相当于default语句块
? ? }

要解决这个问题,只要拿掉最后一个whencontinue就可以了,改写成如下形式:

1
2
3
4
5
6
7

use 5.010;
given( $ARGV[0] ) {
? ? when( $_ ~~ /fred/i ) { say 'Name has fred in it'; continue }
? ? when( $_ ~~ /^Fred/ ) { say 'Name starts with Fred'; continue }
? ? when( $_ ~~ 'Fred' ?) { say 'Name is Fred'; break } #
现在就对了!
? ? when( 1 == 1 ? ? ? ?) { say "I don't see a Fred" } ?#
这里的when(1==1)可改写成default
? ? }

多个项目的when匹配

有些时候需要遍历很多元素,但given只能一次接受一个参数,当然可以将given语句放到foreach里面循环测试。比如要遍历@names,依次将各元素赋值到$name,然后再用given

1
2
3
4
5
6

use 5.010;
foreach my $name ( @names ) {
? ? given( $name ) {
? ? ? ? ...
? ? ? ? }
? ? }

如果使用given-when语句,想必大家首先想到的就是上面的方法,实际上要遍历多个元素时就就不必使用given了,使用foreach的简写形式,让它给当前正在遍历的元素起个化名$_。此外若要用智能匹配,当前元素就只能是$_

use 5.010;
foreach ( @names ) { #
不要使用命名变量!
? ? when( /fred/i ) { say 'Name has fred in it'; continue }
? ? when( /^Fred/ ) { say 'Name starts with Fred'; continue }
? ? when( 'Fred' ?) { say 'Name is Fred'; }
? ? default ? ? ? ? { say "I don't see a Fred" }
? ? }

一般在遍历的时候,总希望可以看到当前的工作状态。可以在foreach语句块中写上其他的语句,比如say:

1
2
3
4
5
6
7
8
9

use 5.010;
foreach ( @names ) { #
不要使用命名变量!
? ? say "/nProcessing $_";
? ? when( /fred/i ) { say 'Name has fred in it'; continue }
? ? when( /^Fred/ ) { say 'Name starts with Fred'; continue }
? ? when( 'Fred' ?) { say 'Name is Fred'; }
? ? say "Moving on to default...";
? ? default ? ? ? ? { say "I don't see a Fred" }
? ? }

?



本章练习
1
、用given-when结构写一个程序,根据输入的数字,如果能被3整除,就打印“Fizz”,如果能被5整除就打印“Bin”,如果能被7整除就打印“Sausag”。比如输入数字15,程序打印“Fizz”和“Bin

1
2
3
4
5
6
7
8
9
10
11

#!/usr/binperl -w

use strict;

use 5.010;

given($ARGV[0]){
? ? when(not $_ % 3){say 'Fizz';continue}
? ? when(not $_ % 5){say 'Bin';continue}
? ? when(not $_ % 7){say 'sausage'}
}

# perl ex_13_1.pl 3
Fizz
# perl ex_13_1.pl 15
Fizz
Bin
# perl ex_13_1.pl 105
Fizz
Bin
sausage
2
、使用foreach-when写个程序,要求从命令行遍历某个目录下的文件,并报告每个文件的可读、可写和可执行属性状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#!/usr/bin/perl -w

use strict;

use 5.010;

my $SourcePath = $ARGV[0];
opendir MYDIR,$SourcePath or die "can't open $SourcePath :$!";

chdir $SourcePath;
foreach (readdir MYDIR){
say "/e[32m==============================/e[0m";
when(-x $_){say "$SourcePath/$_ /e[1;32mexecutable!/e[0m";continue}
when(-r $_){say "$SourcePath/$_ /e[1;35mreadable !/e[0m";continue}
when(-w $_){say "$SourcePath/$_ /e[1;33mwritable !/e[0m"}
}
closedir MYDIR

--我这里从命令行读取用户输入的目录,如果目录不存在,报错退出,否则切换当前路径到该目录下,依次遍历目录中的文件,使用when语句判断文件可读写情况。如果是...则直接略过,在测试文件属性时用到了前面介绍的一个技巧,即_也就是下划线,它代表了上一个测试的文件。
运行结果:

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读