分类: 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函数配合三目操作符。当然让程序识别真/假,比判断是否定义方便的多。 大部分语言的返回值会限定为0或1,但||这个操作符有更有趣的特性:假如左侧操作符为真,即返回左侧操作数,否则返回右侧操作数(或者第二个操作数) 。&&符号同样返回最后一个表达式的值,但这在实际应用中很少使用。这些操作符的返回值并不影响操作返回的布林值,同时,这些操作符不去识别字符串或者是数字,甚至指针,它们返回的是第一个使得表达式是真/假的值。 这个属性使得你可以为变量,函数或更长的表达式确立缺省值。下面这个例子将$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 在高版本的perl(5.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其他 ||操作符的使用参阅perlop(1)或者Programming Perl的第3章; 函数defined 和exist可参阅perlfunc(1)或 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,26和30的位置。虽然我们可以计算出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-bit或8bit的数据(ASCI&ASCII)
1.1.4 其它
函数 pack, unpack, 和 substr 请参阅 perlfunc(1) 或者 Programming Perl的29章; 子程序cut2fmt的应用参阅第1.24节; unpack在二进制中的应用参阅第 8.24节