Chinaunix首页 | 论坛 | 博客
  • 博客访问: 25698
  • 博文数量: 13
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-05 16:13
文章分类
文章存档

2016年(1)

2014年(12)

我的朋友

分类: PERL

2014-01-06 16:47:52

1.2 赋值缺省值

1.2.1 问题描述

当希望为一个标量变量提供缺省值,前提是这个标量变量没有被另外赋值。这种情况经常发生在当你需要一个硬代码的初始值,但这个初始值可能被命令行或环境变量覆盖。

1.2.2 解决方案

||||=操作符,这两个操作符可用于字符串和数字

$a = $b || $c; # use $b if $b is true, else $c

$x ||= $y; # set $x to $y unless $x is already true

但是当你的变量中含有0,“0”或“”时,需要用 defined代替上面的符号:

$a = defined($b) ? $b : $c; # use $b if $b is defined, else $c

# the "new" defined-or operator from future perl

use v5.9;

$a = $b // $c;#perl5.9b版本以后的功能

1.2.3 讨论

defined||的不同之处在于他们对“真/假”的处理上。假如你需要使用0,“0”或者””这三个符号时,不能使用符号||,它会认为这三个符号为“假”。在低版本(5.9)之前,需要使用defined函数配合三目操作符。当然让程序识别真/假,比判断是否定义方便的多。

大部分语言的返回值会限定为01,但||这个操作符有更有趣的特性:假如左侧操作符为真,即返回左侧操作数,否则返回右侧操作数(或者第二个操作数) 。&&符号同样返回最后一个表达式的值,但这在实际应用中很少使用。这些操作符的返回值并不影响操作返回的布林值,同时,这些操作符不去识别字符串或者是数字,甚至指针,它们返回的是第一个使得表达式是真/假的值。

这个属性使得你可以为变量,函数或更长的表达式确立缺省值。下面这个例子将$foo设定为$bar的内容,当$bar为假时,设置为DEFAULT VALUE

$foo = $bar || "DEFAULT VALUE";

下面这个例子设定$dir为程序的第一个变量的值,当变量值未给出时,将$dir设定为/tmp中给定的值

$dir = shift(@ARGV) || "/tmp";#We can do this without altering @ARGV:

$dir = $ARGV[0] || "/tmp";

假如程序的第一个变量$ARGV[0]的值为0,(是我们需要用到的值),符号||会认为这个值为假。这个时候我们需要用到perl的三目操作符 ?:

$dir = defined($ARGV[0]) ? shift(@ARGV) : "/tmp";

$dir = @ARGV ? $ARGV[0] : "/tmp";#同上面的例子稍微不同

上面的第二个例子先检查@ARGB中的元素是否为空(此时@ARGB为标量上下文),但@ARGV中的元素个数为0时,表达式值为假,此时$dir的值为/tmp.(@ARGV[0]的值如果为0,仍表示元素个数不为0,表达式值为真,$dir的值为0

下面的例子通过||来为散列%count的键$shell值加1,$shell的值为假时,该键为“/bin/sh”

$count{ $shell || "/bin/sh" }++;

可替代的选项可以很多,但当第一个表达式值为真时,只取第一个表达式

# find the user name on Unix systems

$user = $ENV{USER}

     || $ENV{LOGNAME}

     || getlogin( )

     || (getpwuid($<))[0]

     || "Unknown uid number $<";

赋值运算符|=看起来有些奇怪,但他和其他二进制的赋值操作符的使用方法相同。例如$a+=$b 等价于$a=$a+$b.||=用于当自身的值为假时,设定变量值。下面的例子用于设定$string的值为“Greenwich”除非$string已经被赋值。但当其所赋值为0,“0”“”时,会同样重新赋值。因为||=视这三个值为假

$string ||= "Greenwich";

在赋值的时候不可以用or代替||,因为or的优先级比较低,$a=$b or $c,这个表达式无论$b的值是什么,都会把$b赋值给$a

另外,必要再数组和哈希中使用||||=,它们只在标量中使用,因为该类操作符会把左边的操作数作为标量上下文。对数组和哈希的应用如下:

@a = @b unless @a;          # copy only if empty

@a = @b ? @b : @c;          # assign @b if nonempty, else @c

在高版本的perl5.9)中已经有了////=操作符,它们不会只简单的判断真,假,同时集合了defined的功能,defined-or操作符同时也会像||一样:

$a = defined($b) ? $b : $c;

$a = $b // $c;

$x = defined($x) ? $x : $y;

$x //= $y;

defined(read(FH, $buf, $count)  or  die "read failed: $!";

read(FH, $buf, $count)          err die "read failed: $!";

1.2.4其他

||操作符的使用参阅perlop1)或者Programming Perl的第3章;

函数defined exist可参阅perlfunc1)或 Programming Perl的第29

 

so-a?*?pc??lp^mso-para-margin-left:4.04gd;mso-add-space:auto;text-align:left;text-indent: .1pt;mso-pagination:widow-orphan;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'>#his wasn'


Substr和操作符=~s///m//tr//一起可使得操作仅对匹配的部分有效

# you can test substrings with =~

if (substr($string, -10) =~ /pattern/) {

            print "Pattern matches in last 10 characters\n";

}

# substitute "at" for "is", restricted to first five characters

substr($string, 0, 5) =~ s/is/at/g;#在前五个字符中匹配”is”更换为at

                                     #测试fail

通过substr,甚至可以交换字符串中两个位置字符的值

# exchange the first and last letters in a string

$a = "make a hat";

(substr($a,0,1), substr($a,-1)) =

(substr($a,-1),  substr($a,0,1));

print $a;          # take a ham

尽管unpack不是左值函数,但是当一次性的处理许多“摘录”时,它比substr的运行速度快。而且它可以指定输出的格式。(以下三个符号的操作针对ASCII码的字符串)

小写的“x”后面跟数字,表示向前跳过的字节数;

大写的“X”后面跟数字,表示向后跳过的字节数

@”表示跳过绝对偏移量

# extract column with unpack

$a = "To be or not to be";

$b = unpack("x6 A6", $a);  # skip 6, grab 6

print $b;#or not

($b, $c) = unpack("x6 A2 X5 A2", $a);

 # forward 6, grab 2; backward 5, grab 2

print "$b\n$c\n";

#output or

        be

也许有的时候我们在切割数据时,更倾向于在指定的栏位,例如切割的位置在8,14,20,2630的位置。虽然我们可以计算出unpack的格式为,“A7,A6,A6,A6,A4,A*”但这个计算过程对perl的程序员来说也许很伤脑筋,我们可以通过子程序cut2fmt解决

sub cut2fmt {

    my(@positions) = @_;

    my $template   = '';

    my $lastpos    = 1;

    foreach $place (@positions) {

        $template .= "A" . ($place - $lastpos) . " ";

        $lastpos   = $place;

    }

    $template .= "A*";

    return $template;

}

$fmt = cut2fmt(8, 14, 20, 26, 30);

print "$fmt\n"; #A7 A6 A6 A6 A4 A*

这个unpack功能强大,它不仅可以应用与文本的处理,它也是文本和二进制文件的桥梁,在本节中,所有的例子中,假设字符为7-bit8bit的数据(ASCI&ASCII

1.1.4 其它

函数 pack, unpack, substr 请参阅 perlfunc(1) 或者 Programming Perl29; 子程序cut2fmt的应用参阅第1.24; unpack在二进制中的应用参阅第 8.24
阅读(620) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~