第三章 Perl語言(三)-流程控制没佑、標量毕贼、數(shù)組

流程控制

最基礎的流程就是從開始到結束温赔,一行一行的執(zhí)行:

say 'At start';
say 'In middle';
say 'At end';

條件分支

if指令會在條件表達式為真時執(zhí)行相應的動作:

say 'Hello, Bob!' if $name eq 'Bob';

這個是后綴形式蛤奢,在執(zhí)行簡單表達式時非常有用。還有一種是當條件表達式為真時執(zhí)行塊的形式:

if ($name eq 'Bob')
{
say 'Hello, Bob!';
found_bob();
}

此時條件表達式的****圓括號不可省略陶贼,且要有塊的形式(那就是大括號也不能势》贰)。****

條件表達式可以由多項組成:

if ($name eq 'Bob' && not greeted_bob())
{
say 'Hello, Bob!';
found_bob();
}

使用后綴形式拜秧,添加括號增加可讀性:

greet_bob() if ($name eq 'Bob' && not greeted_bob());

unless指令的意思與if相反痹屹,就是當條件為假時執(zhí)行對應動作,它的用法和if一樣枉氮。

say "You're not Bob!" unless $name eq 'Bob';

unless (is_leap_year() and is_full_moon())
{
frolic();
gambol();
}

if和unless都支持else指令志衍。執(zhí)行條件與主句條件相反。

if ($name eq 'Bob')
{
say 'Hi, Bob!';
greet_user();
}
else
{
say "I don't know you.";
shun_user();
}



unless ($name eq 'Bob')
{
say "I don't know you.";
shun_user();
}
else
{
say 'Hi, Bob!';
greet_user();
}

unless與if表達的意思相反聊替,可以相互轉(zhuǎn)換楼肪,根據(jù)自己的喜好,挑個順手的用就好惹悄。

如果你有很多的條件要逐一比對春叫,你可以在if中使用elsif指令:

if ($name eq 'Bob')
{
say 'Hi, Bob!';
greet_user();
}
elsif ($name eq 'Jim')
{
say 'Hi, Jim!';
greet_user();
}
else
{
say "You're not my uncle.";
shun_user();
}

下面這個會報錯,沒有(else if)這種語法:

if ($name eq 'Rick')
{
say 'Hi, cousin!';
}
# warning; syntax error
else if ($name eq 'Kristen')
{
say 'Hi, cousin-in-law!';
}

三目操作符

三目操作符(? :)可以根據(jù)給定的條件選擇執(zhí)行表達式.條件表達式為真時執(zhí)行表達式1泣港,條件表達式為假時執(zhí)行表達式2:
條件表達式 ? 表達式1 : 表達式2

my $time_suffix = after_noon($time)
? 'afternoon'
: 'morning';

這里有個例子展示了三目操作符不僅能用于值還能用于變量:
push @{ rand() > 0.5 ? @red_team : @blue_team }, Player->new;

****短路****
Perl在遇到復雜的條件表達式時具有短路行為暂殖,原則就是:當Perl能確定整個多項表達式的真假時就不會繼續(xù)去計算每一個子項。

say 'Both true!' if ok( 1, 'subexpression one' )
&& ok( 1, 'subexpression two' );
done_testing();

ok 1 - subexpression one
ok 2 - subexpression two
Both true!

上例中2個子項都執(zhí)行了当纱,下面這個例子中只需要計算第一項就夠了:

say 'Both true!' if ok( 0, 'subexpression one' )
&& ok( 1, 'subexpression two' );

not ok 1 - subexpression one

邏輯運算中有個特征:與運算中呛每,有一項為假時就能確定整個值為假;或運算中坡氯,有一項為真就能確定整個值為真莉给。

條件指令的語境

條件指令:if毙石,unless,還有三元條件操作符提供的都是****布爾語境****颓遏。
比較操作符徐矩,如eq,==叁幢,ne滤灯,and, !=也都產(chǎn)生的是布爾值曼玩。
Perl沒有單獨的真值和單獨的假值鳞骤。任何數(shù)值為0的數(shù)字都是假,如0, 0.0, 0e0, 0x0黍判。字符串'0'和空字符''也是假值豫尽。但是字符串'0.0', '0e0'不是假值∏晏空列表和undef都是假值美旧。空數(shù)組和空哈希在標量環(huán)境中返回數(shù)字0贬墩,所以在布爾語境中也是假值榴嗅。數(shù)組中只要擁有一個元素(哪怕是undef),那么這個數(shù)組在布爾語境中也是真值陶舞。類似的嗽测,哈希中只要有一個元素,即使鍵和值是undef肿孵,也是真值唠粥。

循環(huán)

foreach (1 .. 10)
{
say "$_ * $_ = ", $_ * $_;
}

跟if和unless一樣,也支持后綴:

say "$_ * $_ = ", $_ * $_ for 1 .. 10;

也可以顯式使用自定義的變量:

for my $i (1 .. 10)
{
say "$i * $i = ", $i * $i;
}

注意:改變變量的值停做,會修改原始值:

my @nums = 1 .. 10;
$_ **= 2 for @nums;
#@nums數(shù)值變了

所以當修改常量時就會報錯:

$_++ and say for qw( Huex Dewex Louid );

****迭代和范圍界定****
循環(huán)中可能會出現(xiàn)這樣一個問題:變量在內(nèi)部嵌套中是可見的晤愧,所以當使用默認變量$_,并且未對它做保護時就會出問題雅宾。此類問題非常隱蔽:

for (@values)    #默認使用$_
{
topic_mangler();
}
sub topic_mangler
{
s/foo/bar/;    # $_繼續(xù)有效养涮,修改$_就修改連原始數(shù)組!
}

所以:使用自定義的有名字的變量總是一個更好的選擇眉抬。

****C風格循環(huán)****

my $i = 'pig';
for ($i = 0; $i <= 10; $i += 2)
{
say "$i * $i = ", $i * $i;
}

****while和until****
while贯吓,當條件為真時執(zhí)行,直到條件為假蜀变。until與while相反悄谐,條件假時執(zhí)行,直到條件為真库北。(可以互換爬舰,挑自己順手的用)

while (1) { ... }    #無限循環(huán)


while (my $value = shift @values)
{
say $value;
}
此循環(huán)有個隱秘的問題:當元素值為假值時就會退出循環(huán)们陆,而并不一定是耗盡了整個數(shù)組。
do
{
say 'What is your name?';
my $name = <>;
chomp $name;
say "Hello, $name!" if $name;
} until (eof);

循環(huán)至少執(zhí)行一次情屹。

****循環(huán)嵌套****
循環(huán)嵌套就是循環(huán)內(nèi)有循環(huán):

for my $suit (@suits) {
for my $values (@card_values) { ... }
}

****循環(huán)控制****
next-立即進入下一循環(huán):

while (<$fh>)
{
next if /\A#/;
...
}

last-立即結束循環(huán)坪仇。

while (<$fh>)
{
next if /\A#/;
last if /\A__END__/;    #看到文件結尾標志立即結束    
...
}

redo-重新進入當前迭代(無需評估循環(huán)條件)。

while (<$fh>)
{
print;
redo;    #不能這樣寫垃你,因為這樣會不停重復循環(huán)    
...    #這后面的不會被執(zhí)行到
}

循環(huán)嵌套時椅文,可能不容易讓人理清楚結構,這時可以使用標簽:

LINE:
while (<$fh>)
{
chomp;
PREFIX:
for my $prefix (@prefixes)
{
next LINE unless $prefix;
say "$prefix: $_";
# next PREFIX is implicit here
}
}

****continue語句****
continue的使用非常少見惜颇,使用時一般和while, until, when, for循環(huán)一同使用皆刺。它將始終被執(zhí)行之前的條件再次進行計算,就像C語言的一個for循環(huán)中的第三部分凌摄。

while ($i < 10 ) {
next unless $i % 2;
say $i;
}
continue {
say 'Continuing...';
$i++;
}

Continuing...
1
Continuing...
Continuing...
3
Continuing...
Continuing...
5
Continuing...
Continuing...
7
Continuing...
Continuing...
9
Continuing...


注意:如果因為last或者redo指令離開當前迭代羡蛾,那么continue 塊當次不會被執(zhí)行。

****switch****
該功能是實驗性的锨亏,暫不介紹痴怨。

****尾部調(diào)用****
當函數(shù)中最后一個表達式調(diào)用函數(shù)時就是尾部調(diào)用。被調(diào)用的函數(shù)返回值將成為主函數(shù)的返回值屯伞。

sub log_and_greet_person
{
my $name = shift;
log( "Greeting $name" );
return greet_person( $name );
}

標量

標量腿箩,一個單一的豪直、離散的值劣摇。標量是Perl的基本數(shù)據(jù)類型。它可以是一個字符串弓乙,一個整型數(shù)字末融,浮點數(shù)字,一個文件句柄暇韧,或者是一個引用——但肯定是一個單一的值勾习。標量變量可以是詞法作用域,包作用域懈玻,也可以是全局作用域巧婶。標量變量總是使用美元($)記號。

標量和類型

my $value;
$value = 123.456;
$value = 77;
$value = "I am Chuck's big toe.";
$value = Store::IceCream->new;

不同語境下會發(fā)生類型轉(zhuǎn)換涂乌,Perl中的數(shù)字和字符串可以根據(jù)語境自動轉(zhuǎn)換艺栈,比如將數(shù)字視為字符串:

my $zip_code = 97123;    #數(shù)字
my $city_state_zip = 'Hillsboro, Oregon' . ' ' . $zip_code;    #字符串

也可以對字符串使用++操作符:

my $call_sign = 'KBMIU';
my $next_sign = ++$call_sign;    # 返回新值,KBMIV
my $curr_sign = $call_sign++;    # 返回舊值湾盒,然后再更新


my $new_sign = $call_sign + 1;   # 這個可與上面2個效果不一樣湿右,這個值是1

++操作符用在數(shù)字上的行為是加一罚勾;但用在字符串上的行為是:a到b吭狡,z到aa;ZZ9到AAA0划煮, ZZ09 到ZZ10,這樣增長缔俄。

引用類型也能進行轉(zhuǎn)換般此,在字符串語境下計算引用時牵现,引用會返回字符串铐懊;在數(shù)字語境下會返回數(shù)字:

my $authors = [qw( Pratchett Vinge Conway )];
my $stringy_ref = '' . $authors;    #字符串
my $numeric_ref = 0 + $authors;  #數(shù)字

數(shù)組

數(shù)組,Perl語言的內(nèi)置數(shù)據(jù)結構瞎疼,包含0個或多個標量值科乎。你可以通過索引訪問各個數(shù)組成員,并且可以隨意添加和刪除元素贼急,數(shù)組變大和縮小都是自動處理的。@記號表示一個數(shù)組太抓。
聲明一個數(shù)組:

my @items;

數(shù)組元素

使用標量記號($)來訪問一個數(shù)字元素:

# @cats表示一堆貓,現(xiàn)在要訪問第一貓
my $first_cat = $cats[0];

# 標量語境返回元素個數(shù)
my $num_cats = @cats;

# 也是標量語境
say 'I have ' . @cats . ' cats!';
# addition
my $num_animals = @cats + @dogs + @fish;

# 布爾語境
say 'Yep, a cat owner!' if @cats;

#元素索引從0開始
my $first_index = 0;
my $last_index = @cats - 1;    # 或者 my $last_index = $#cats;
say "My first cat has an index of $first_index, "
. "and my last cat has an index of $last_index."


#還支持從最后面開始定位碴倾,-1是最后一個元素掉丽,-2是倒數(shù)第二個……,不過要注意數(shù)量要夠
my $last_cat = $cats[-1];
my $second_to_last_cat = $cats[-2];

數(shù)組賦值:

my @cats;
$cats[3] = 'Jack';
$cats[2] = 'Tuxedo';
$cats[0] = 'Daisy';
$cats[1] = 'Petunia';
$cats[4] = 'Brad';
$cats[5] = 'Choco';

my @cats = ( 'Daisy', 'Petunia', 'Tuxedo', ... );

數(shù)組操作

  • push 往數(shù)組末尾追加元素捶障,一個或多個
  • pop 從數(shù)組末尾彈出一個元素
my @meals;
# what is there to eat?
push @meals, qw( hamburgers pizza lasagna turnip );
# ... but your nephew hates vegetables
pop @meals;
  • shift 從數(shù)組開頭彈出一個元素
  • unshift 在數(shù)組開頭插入元素,一個或多個
# expand our culinary horizons
unshift @meals, qw( tofu spanakopita taquitos );
# rethink that whole soy idea
shift @meals;
  • splice 可以刪除數(shù)組中某段元素担平,也可以往數(shù)組中覆蓋或插入元素
my ($winner, $runnerup) = splice @finalists, 0, 2;
# or
my $winner = shift @finalists;
my $runnerup = shift @finalists;
  • each 迭代返回元素的索引和值
while (my ($position, $title) = each @bookshelf) {
say "#$position: $title";
}

數(shù)組切片

標量每次只能訪問數(shù)組中的單個元素锭部,而有個叫數(shù)組切片的結構可以讓你訪問數(shù)組中的一系列(0個或多個)元素。
我們已經(jīng)知道了空免,表示多個元素需要用到記號@:

my @youngest_cats = @cats[-1, -2];
my @oldest_cats = @cats[0 .. 2];
my @selected_cats = @cats[ @indexes ];

@users[ @replace_indices ] = @replace_users;

數(shù)組切片的索引為列表語境:

# function called in list context
my @hungry_cats = @cats[ get_cat_indices() ];


# single-element array slice; list context
@cats[-1] = get_more_cats();
# single-element array access; scalar context
$cats[-1] = get_more_cats();

****數(shù)組和語境****
在列表語境中,數(shù)組展平為列表扼菠。

my @cats = qw( Daisy Petunia Tuxedo Brad Jack Choco );
my @dogs = qw( Rodney Lucky Rosie );
take_pets_to_vet( @cats, @dogs );
sub take_pets_to_vet
{
# BUGGY: do not use!
my (@cats, @dogs) = @_;
...
}

扁平化有時也會造成混淆:

# creates a single array, not an array of arrays
my @numbers = (1 .. 10, (11 .. 20, (21 .. 30)));

# parentheses do not create lists
my @numbers = ( 1 .. 10, 11 .. 20, 21 .. 30 );
# creates a single array, not an array of arrays
my @numbers = 1 .. 30;

****數(shù)組插值****
數(shù)組在內(nèi)插到雙引號包圍的字符串中時,會返回這樣一個字符串:由$"的值將每個元素連接起來循榆。
$"的值默認是一個空格。

my @alphabet = 'a' .. 'z';
say "[@alphabet]";

[a b c d e f g h i j k l m
n o p q r s t u v w x y z]


自定義$" 以便輸出特定形式的結果:
local $" = ')(';
say "(@sweet_treats)";
(pie)(cake)(doughnuts)(cookies)(cinnamon roll)
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末映挂,一起剝皮案震驚了整個濱河市盗尸,隨后出現(xiàn)的幾起案子柑船,更是在濱河造成了極大的恐慌,老刑警劉巖泼各,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扣蜻,居然都是意外死亡,警方通過查閱死者的電腦和手機锐极,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門芳肌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人庇勃,你說我怎么就攤上這事槽驶。” “怎么了罕拂?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵全陨,是天一觀的道長。 經(jīng)常有香客問我辱姨,道長,這世上最難降的妖魔是什么枢舶? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮躏尉,結果婚禮上后众,老公的妹妹穿的比我還像新娘胀糜。我一直安慰自己蒂誉,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布怖竭。 她就那樣靜靜地躺著陡蝇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪登夫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天鸦致,我揣著相機與錄音涣楷,去河邊找鬼。 笑死狮斗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的折砸。 我是一名探鬼主播沙峻,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼摔寨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起删顶,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斑鼻,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坚弱,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡关摇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了些楣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宪睹。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖亭病,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情促煮,我是刑警寧澤整袁,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站坐昙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏襟士。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝶溶。 院中可真熱鬧,春花似錦抖所、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弦悉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稽莉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工劈猪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留良拼,地道東北人岸霹。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓将饺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親予弧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 53.計算字符 在字符串中獲取字符值的數(shù)量, 可以使用字符串字符屬性中的計數(shù)屬性: let unusualMena...
    無灃閱讀 1,091評論 0 4
  • 數(shù)組在程序設計中杀捻,為了處理方便蚓庭, 把具有相同類型的若干變量按有序的形式組織起來。這些按序排列的同類數(shù)據(jù)元素的集合稱...
    朱森閱讀 3,926評論 2 13
  • 今天很特別的一天垢袱,我在整個的跟TP 7教練團溝通過程中都是有好為人師的標準在港柜,內(nèi)在投射出來的是我比他們強咳榜,沒有活出...
    Hi_張閱讀 127評論 0 0
  • 春來乍暖的季節(jié)爽锥,斜靠在窗前總抻不住思緒漂浮不定的亂想。 忽念起去年聽過的一場音樂會氯夷,音樂會的歌唱者們身份很特別,之...
    坤兒Joy閱讀 602評論 0 2
  • 現(xiàn)在的我是快樂的席吴,盡管不知道明天在哪里捞蛋,但知道方向在哪里孝冒,這條路充滿了陽光和花香拟杉。 選擇進入鮮花這個行...
    夜涼如歌閱讀 382評論 0 0