- Perl語言IC設(shè)計(jì)實(shí)踐
- 滕家海編著
- 2212字
- 2022-02-08 17:37:59
1.3 改進(jìn)命令行參數(shù)
輸入?yún)?shù)都在一個(gè)數(shù)組(@ARGV)中,這樣使用起來還有些不便。我們還需要便捷地知道對應(yīng)某個(gè)選項(xiàng)的參數(shù)值。
在開始編寫代碼之前,我們先約定:
1)所有的輸入?yún)?shù),由選項(xiàng)和對應(yīng)的參數(shù)值組成。不存在某個(gè)不屬于任何選項(xiàng)的參數(shù)值。
2)每個(gè)選項(xiàng)對應(yīng)至少一個(gè)參數(shù)值。不支持沒有參數(shù)值的選項(xiàng),即類似開關(guān)的選項(xiàng)。
我們以Linux中常見的復(fù)制命令為例:
cp -i file_a file_b
其中“-i”就是一個(gè)沒有任何參數(shù)值的選項(xiàng),該命令只在file_b存在的情況下,詢問用戶是否繼續(xù)復(fù)制動作覆蓋file_b。file_a或file_b都不屬于任何選項(xiàng),cp命令只是依據(jù)它們的位置來決定其意義:第一個(gè)參數(shù)作為輸入文件,第二個(gè)參數(shù)作為輸出文件。
如果使用Perl程序完成上述cp命令的功能,依照上面的約定,程序(假設(shè)為mycp)的參數(shù)可設(shè)計(jì)成如下:
-input file -output file -overlap [yes|no]
相應(yīng)地,我們的程序,需要這樣運(yùn)行:
mycp -input file_a -output file_b -overlap no
當(dāng)然,這些選項(xiàng)的相對位置是隨意的,也可以這樣運(yùn)行:
mycp -overlap no -output file_b -input file_a
本節(jié),我們將改進(jìn)代碼1-1的讀取命令行參數(shù)的程序,把參數(shù)都存儲到一個(gè)散列(hash)中。我們假設(shè)每個(gè)選項(xiàng)對應(yīng)一個(gè)參數(shù)值,不多也不少,并且用戶的輸入是正確的:-optA pv_a -optB pv_b …。
代碼1-2 ch01/read_argument_v2.pl
1 #!/usr/local/bin/perl 2 3 my ($opt, %value_of_opt) ; 4 5 for my $arg ( @ARGV ) { 6 if ( $arg =~ /^-/ ) { 7 $opt = $arg; 8 } 9 else { 10 $value_of_opt{$opt} = $arg; 11 } 12 } 13 14 for my $opt ( keys %value_of_opt ) { 15 print "$opt => $value_of_opt{$opt}\n"; 16 } 17 18 exit 0;
如果我們運(yùn)行:
./read_argument_v2.pl -a a1 -b b1 -c c1
那么程序會輸出:
Command is: ./read_argument_v2.pl -a => a1 -b => b1 -c => c1
第3行,聲明了兩個(gè)變量:一個(gè)標(biāo)量$opt,一個(gè)散列%value_of_opt。
第6~11行,是一個(gè)if/else判斷結(jié)構(gòu)。
第6行條件中的$arg =~ /^-/是一個(gè)正則表達(dá)式匹配,如果$arg以短橫線(“-”)開頭,那么該匹配返回1,否則返回空(就是什么都沒有),通常稱之為空字符串。有關(guān)正則表達(dá)式的內(nèi)容,留在第3章進(jìn)行詳細(xì)介紹。
第7行,把$arg的值賦值給$opt,留給下一次循環(huán)(第10行)使用。
第10行,把$arg賦值給散列中對應(yīng)的鍵$opt。也就是說,給散列%value_of_opt中增加一個(gè)鍵/值對,其中鍵是$opt,值是$arg。
下面我們依次介紹代碼1-2中出現(xiàn)的散列、判斷結(jié)構(gòu)if/else以及“真”與“假”。
1.3.1 散列
散列就是無序的鍵/值對,假設(shè)只有標(biāo)量和數(shù)組,沒有散列,理論上,也可以表示各類數(shù)據(jù)?,F(xiàn)有一組如下數(shù)據(jù):
ZheJiang HangZhou JiangXi NanChang XiZang LaSa …
可以如下存儲數(shù)據(jù):
my @provinces = ("ZhaJiang", "JiangXi", "XiZang"); my @pccs = ("HangZhou", "NanChang", "LaSa");
假設(shè)我們想知道江西的省會,可以通過一個(gè)循環(huán),找到JiangXi在數(shù)組@provinces中的序號(即1,數(shù)組的序號從0開始),然后把這個(gè)1存儲在某個(gè)變量中(比如$n),然后取出$pccs[$n],這就是我們想要的信息。
由于這樣的情形很常見,需要更高效簡便的處理方式,因此很多高級語言都提供了散列或者功能類似的數(shù)據(jù)類型。Perl的散列名必須以%開頭,后面緊跟一個(gè)字母或者下劃線,后面還可以繼續(xù)跟多個(gè)字母、數(shù)字或下劃線。散列的初始化如下所示:
%pcc_of = ( 'ZheJiang' => 'HangZhou', 'JiangXi' => 'NanChang', 'XiZang' => 'LaSa', );
與數(shù)組類似,散列由圓括號包圍,鍵/值對用逗號分隔。每個(gè)單元都指定了一個(gè)鍵,在=>的左邊;同時(shí)指定了與這個(gè)鍵配對的值,在=>的右邊。鍵和值都是標(biāo)量。如果要取用某個(gè)鍵指向的值,可以這樣:
print $pcc_of{'JiangXi'}, "\n";
輸出:
NanChang
散列中的鍵是唯一的,即同一個(gè)散列中不存在兩個(gè)同名的鍵。
散列的常用函數(shù)有keys、values等。keys返回散列的全部的鍵,組成一個(gè)數(shù)組。values返回散列的所有的值,組成一個(gè)數(shù)組。需要留意的是,keys返回的數(shù)組中,各鍵的次序與該散列初始化化時(shí)各鍵的次序無關(guān)。
散列是靈活的,可以增減鍵值對??墒褂胐elete函數(shù)進(jìn)行刪除操作,也可直接賦值進(jìn)行新增操作。
delete $one_hash{'akey'}; $one_hash{'akey'} = "something";
1.3.2 判斷結(jié)構(gòu)if
常用的判斷結(jié)構(gòu)有if/elsif/else。其中elsif/else分支是可選的,elsif分支可以有多個(gè),else分支最多只能有一個(gè)。
if ( condition1 ) { sentences1 … } elsif ( condition2 ) { sentences2 … } elsif ( condition3 ) { sentences3 … } else { sentencesN … } outer_sentence …
上述判斷結(jié)構(gòu)會從if的條件開始判斷,如果condition1為“真”,則執(zhí)行后面大括號中的語句sentences1;如果為“假”,則繼續(xù)檢查下一個(gè)條件,直到某個(gè)分支的條件為“真”,就執(zhí)行那個(gè)分支的語句,執(zhí)行該語句后,離開整個(gè)if/elsif/else結(jié)構(gòu)。如果沒有任何條件為“真”,且存在else分支,則執(zhí)行else分支的語句。
無論執(zhí)行哪個(gè)分支的語句,都會離開整個(gè)判斷結(jié)構(gòu),來到結(jié)構(gòu)外部,繼續(xù)后面的語句outer_sentence。
1.3.3 “真”與“假”
什么是“真”,什么是“假”?這既可以是一個(gè)深奧的哲學(xué)問題,也可以是一個(gè)簡單的Perl語法問題。在這里,我們僅討論后者。
Perl沒有提供專門的變量或常量來表示“真”與“假”。任何標(biāo)量(或常量)都可以成為判斷結(jié)構(gòu)的條件。那么Perl怎么判斷這個(gè)標(biāo)量是“真”還是“假”呢?它有以下規(guī)則:
- 未被賦值的,是假;
- 數(shù)字0,字符串'0'(零),空字符串'',是假;
- 其余皆為真。
my $t1 = 0; # false my $t2 = '0'; # false my $t3 = '' ; # false my $t4 = ' '; # true
除了單個(gè)的“真”“假”表達(dá)式,Perl還支持邏輯表達(dá)式的組合。有兩組“或與非”邏輯操作符會經(jīng)常使用。
第1組是“!”“&&”“||”(見表1-1)。
表1-1 邏輯操作符1

第2組是“not”“and”“or”(見表1-2)。
表1-2 邏輯操作符2

不用背誦記憶它們之間的優(yōu)先級,只要使用圓括號即可,例如:
(expr1 or expr2) and (expr3 or expr4) and (! expr5) …
這樣可使代碼的邏輯結(jié)構(gòu)更清晰,也避免了我們對優(yōu)先級的預(yù)期出現(xiàn)誤判。
既然有兩組邏輯操作符,那么如何選擇呢?有沒有特殊的規(guī)則需要記憶?請放心,沒有!我常用的是“and”“or”“!”,因?yàn)槲以谳斎?amp;&和||這類“疊詞”時(shí)常常會少輸入一個(gè)字符,造成語法錯誤。使用!而不是not的原因是,后者字符多了兩倍,而且前者具有很好的警示作用(即取“反”)。
不需要記憶的優(yōu)先級:
1)!、&&、||這一組的各個(gè)邏輯操作符的優(yōu)先級分別高于相對應(yīng)的not、and、or。
2)同一組內(nèi),not(!)的優(yōu)先級高于and(&&)的優(yōu)先級,and(&&)的優(yōu)先級高于or(||)的優(yōu)先級。
3)將優(yōu)先級按從高到低排序并匯總起來就是:! 高于 not 高于 && 高于 and 高于 || 高于 or。
- Spring 5.0 By Example
- 零基礎(chǔ)玩轉(zhuǎn)區(qū)塊鏈
- JavaScript+jQuery開發(fā)實(shí)戰(zhàn)
- 編寫整潔的Python代碼(第2版)
- The React Workshop
- Oracle BAM 11gR1 Handbook
- 從0到1:Python數(shù)據(jù)分析
- R Deep Learning Cookbook
- Julia高性能科學(xué)計(jì)算(第2版)
- Python深度學(xué)習(xí)原理、算法與案例
- HTML5與CSS3權(quán)威指南
- 關(guān)系數(shù)據(jù)庫與SQL Server 2012(第3版)
- Building Web and Mobile ArcGIS Server Applications with JavaScript(Second Edition)
- ASP.NET Core 2 High Performance(Second Edition)
- 網(wǎng)頁設(shè)計(jì)理論與實(shí)踐