⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1894.html

📁 著名的linux英雄站点的文档打包
💻 HTML
📖 第 1 页 / 共 5 页
字号:
代码:
$ a=5; b=7; c=2 
$ echo $(( a+b*c )) 
19 
$ echo $(( (a+b)/c )) 
6 
$ echo $(( (a*b)%c)) 
1


在 $(( )) 中的變量,可用 $ 符號來替換,也可以不用,如: 
$(( $a + $b * $c)) 也可得到 19 的結果 

此外,$(( )) 還可作不同進位(如二進位、八進位、十六進位)作運算呢,只是,輸出結果皆為十進位而已: 
echo $((16#2a)) 結果為 42 (16進位轉十進位) 
以一個實用的例子來看看吧: 
假如當前的 umask 是 022 ,那麼新建文件的權限即為: 
代码:
$ umask 022 
$ echo "obase=8;$(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc 
644


事實上,單純用 (( )) 也可重定義變量值,或作 testing: 
a=5; ((a++)) 可將 $a 重定義為 6 
a=5; ((a--)) 則為 a=4 
a=5; b=7; ((a < b)) 會得到 0 (true) 的返回值。 
常見的用於 (( )) 的測試符號有如下這些: 

<:小於 
>:大於 
<=:小於或等於 
>=:大於或等於 
==:等於 
!=:不等於

不過,使用 (( )) 作整數測試時,請不要跟 [ ] 的整數測試搞混亂了。(更多的測試我將於第十章為大家介紹) 

怎樣?好玩吧.. ^_^ okay,這次暫時說這麼多... 
上面的介紹,並沒有詳列每一種可用的狀態,更多的,就請讀者參考手冊文件囉...

9) $@ 與 $* 差在哪? 

要說 $@ 與 $* 之前,需得先從 shell script 的 positional parameter 談起... 
我們都已經知道變量(variable)是如何定義及替換的,這個不用再多講了。 
但是,我們還需要知道有些變量是 shell 內定的,且其名稱是我們不能隨意修改的, 
其中就有 positional parameter 在內。 

在 shell script 中,我們可用 $0, $1, $2, $3 ... 這樣的變量分別提取命令行中的如下部份: 
代码:
script_name parameter1 parameter2 parameter3 ...

我們很容易就能猜出 $0 就是代表 shell script 名稱(路逕)本身,而 $1 就是其後的第一個參數,如此類推.... 
須得留意的是 IFS 的作用,也就是,若 IFS 被 quoting 處理後,那麼 positional parameter 也會改變。 
如下例: 
代码:
my.sh p1 "p2 p3" p4

由於在 p2 與 p3 之間的空白鍵被 soft quote 所關閉了,因此 my.sh 中的 $2 是 "p2 p3" 而 $3 則是 p4 ... 

還記得前兩章我們提到 fucntion 時,我不是說過它是 script 中的 script 嗎? ^_^ 
是的,function 一樣可以讀取自己的(有別於 script 的) postitional parameter ,惟一例外的是 $0 而已。 
舉例而言:假設 my.sh 裡有一個 fucntion 叫 my_fun , 若在 script 中跑 my_fun fp1 fp2 fp3 , 
那麼,function 內的 $0 是 my.sh ,而 $1 則是 fp1 而非 p1 了... 

不如寫個簡單的 my.sh script 看看吧: 
代码:
#!/bin/bash 

my_fun() { 
    echo '$0 inside function is '$0 
    echo '$1 inside function is '$1 
    echo '$2 inside function is '$2 
} 

echo '$0 outside function is '$0 
echo '$1 outside function is '$1 
echo '$2 outside function is '$2 

my_fun fp1 "fp2 fp3"

然後在 command line 中跑一下 script 就知道了: 
代码:
chmod +x my.sh 
./my.sh p1 "p2 p3" 
$0 outside function is ./my.sh 
$1 outside function is p1 
$2 outside function is p2 p3 
$0 inside function is ./my.sh 
$1 inside function is fp1 
$2 inside function is fp2 fp3


然而,在使用 positional parameter 的時候,我們要注意一些陷阱哦: 
* $10 不是替換第 10 個參數,而是替換第一個參數($1)然後再補一個 0 於其後﹗ 
也就是,my.sh one two three four five six seven eigth nine ten 這樣的 command line , 
my.sh 裡的 $10 不是 ten 而是 one0 哦... 小心小心﹗ 
要抓到 ten 的話,有兩種方法: 

方法一是使用我們上一章介紹的 ${ } ,也就是用 ${10} 即可。 

方法二,就是 shift 了。 
用通俗的說法來說,所謂的 shift 就是取消 positional parameter 中最左邊的參數( $0 不受影響)。 
其預設值為 1 ,也就是 shift 或 shift 1 都是取消 $1 ,而原本的 $2 則變成 $1、$3 變成 $2 ... 
若 shift 3 則是取消前面三個參數,也就是原本的 $4 將變成 $1 ... 
那,親愛的讀者,你說要 shift 掉多少個參數,才可用 $1 取得 ${10} 呢? ^_^ 

okay,當我們對 positional parameter 有了基本概念之後,那再讓我們看看其他相關變量吧。 
首先是 $# :它可抓出 positional parameter 的數量。 
以前面的 my.sh p1 "p2 p3" 為例: 
由於 p2 與 p3 之間的 IFS 是在 soft quote 中,因此 $# 可得到 2 的值。 
但如果 p2 與 p3 沒有置於 quoting 中話,那 $# 就可得到 3 的值了。 
同樣的道理在 function 中也是一樣的... 

因此,我們常在 shell script 裡用如下方法測試 script 是否有讀進參數: 
代码:
[ $# = 0 ]

假如為 0 ,那就表示 script 沒有參數,否則就是有帶參數... 

接下來就是 $@ 與 $* : 
精確來講,兩者只有在 soft quote 中才有差異,否則,都表示"全部參數"( $0 除外)。 
舉例來說好了: 
若在 command line 上跑 my.sh p1 "p2 p3" p4 的話, 
不管是 $@ 還是 $* ,都可得到 p1 p2 p3 p4 就是了。 
但是,如果置於 soft quote 中的話: 
"$@" 則可得到 "p1" "p2 p3" "p4" 這三個不同的詞段(word)﹔ 
"$*" 則可得到 "p1 p2 p3 p4" 這一整串單一的詞段。 

我們可修改一下前面的 my.sh ,使之內容如下: 
代码:
#!/bin/bash 

my_fun() { 
    echo "$#" 
} 

echo 'the number of parameter in "$@" is '$(my_fun "$@") 
echo 'the number of parameter in "$*" is '$(my_fun "$*")


然後再執行 ./my.sh p1 "p2 p3" p4 就知道 $@ 與 $* 差在哪了 ... ^_^

10) && 與 || 差在哪? 

好不容易,進入兩位數的章節了... 一路走來,很辛苦吧?也很快樂吧? ^_^ 

在解答本章題目之前,先讓我們了解一個概念:return value ﹗ 
我們在 shell 下跑的每一個 command 或 function ,在結束的時候都會傳回父行程一個值,稱為 return value 。 
在 shell command line 中可用 $? 這個變量得到最"新"的一個 return value ,也就是剛結束的那個行程傳回的值。 
Return Value(RV) 的取值為 0-255 之間,由程式(或 script)的作者自行定議: 
* 若在 script 裡,用 exit RV 來指定其值,若沒指定,在結束時以最後一道命令之 RV 為值。 
* 若在 function 裡,則用 return RV 來代替 exit RV 即可。 

Return Value 的作用,是用來判斷行程的退出狀態(exit status),只有兩種: 
* 0 的話為"真"( true ) 
* 非 0 的話為"假"( false ) 

舉個例子來說明好了: 
假設當前目錄內有一份 my.file 的文件,而 no.file 是不存在的: 
代码:
$ touch my.file 
$ ls my.file 
$ echo $?   # first echo 
0 
$ ls no.file 
ls: no.file: No such file or directory 
$ echo $?   # second echo 
1 
$ echo $?   # third echo 
0

上例的第一個 echo 是關於 ls my.file 的 RV ,可得到 0 的值,因此為 true ﹔ 
第二個 echo 是關於 ls no.file 的 RV ,則得到非 0 的值,因此為 false ﹔ 
第三個 echo 是關於第二個 echo $? 的 RV ,為 0 的值,因此也為 true 。 

請記住:每一個 command 在結束時都會送回 return value 的﹗不管你跑甚麼樣的命令... 
然而,有一個命令卻是"專門"用來測試某一條件而送出 return value 以供 true 或 false 的判斷, 
它就是 test 命令了﹗ 
若你用的是 bash ,請在 command line 下打 man test 或 man bash 來了解這個 test 的用法。 
這是你可用作參考的最精確的文件了,要是聽別人說的,僅作參考就好... 
下面我只簡單作一些輔助說明,其餘的一律以 man 為準: 

首先,test 的表示式我們稱為 expression ,其命令格式有兩種: 
代码:
test expression 
or: 
[ expression ]

(請務必注意 [ ] 之間的空白鍵﹗) 
用哪一種格式沒所謂,都是一樣的效果。(我個人比較喜歡後者...) 

其次,bash 的 test 目前支援的測試對像只有三種: 
* string:字串,也就是純文字。 
* integer:整數( 0 或正整數,不含負數或小數點)。 
* file:文件。 
請初學者一定要搞清楚這三者的差異,因為 test 所用的 expression 是不一樣的。 
以 A=123 這個變量為例: 
* [ "$A" = 123 ]:是字串的測試,以測試 $A 是否為 1、2、3 這三個連續的"文字"。 
* [ "$A" -eq 123 ]:是整數的測試,以測試 $A 是否等於"一百二十三"。 
* [ -e "$A" ]:是關於文件的測試,以測試 123 這份"文件"是否存在。 

第三,當 expression 測試為"真"時,test 就送回 0 (true) 的 return value ,否則送出非 0 (false)。 
若在 expression 之前加上一個 " ! "(感嘆號),則是當 expression 為"假時" 才送出 0 ,否則送出非 0 。 
同時,test 也允許多重的覆合測試: 
* expression1 -a expression2 :當兩個 exrepssion 都為 true ,才送出 0 ,否則送出非 0 。 
* expression1 -o expression2 :只需其中一個 exrepssion 為 true ,就送出 0 ,只有兩者都為 false 才送出非 0 。 
例如: 
代码:
[ -d "$file" -a -x "$file" ]

是表示當 $file 是一個目錄、且同時具有 x 權限時,test 才會為 true 。 

第四,在 command line 中使用 test 時,請別忘記命令行的"重組"特性, 
也就是在碰到 meta 時會先處理 meta 再重新組建命令行。(這個特性我在第二及第四章都曾反覆強調過) 
比方說,若 test 碰到變量或命令替換時,若不能滿足 expression 格式時,將會得到語法錯誤的結果。 
舉例來說好了: 
關於 [ string1 = string2 ] 這個 test 格式, 
在 = 號兩邊必須要有字串,其中包括空(null)字串(可用 soft quote 或 hard quote 取得)。 
假如 $A 目前沒有定義,或被定議為空字串的話,那如下的寫法將會失敗: 
代码:
$ unset A 
$ [ $A = abc ] 
[: =: unary operator expected

這是因為命令行碰到 $ 這個 meta 時,會替換 $A 的值,然後再重組命令行,那就變成了: 
[ = abc ] 
如此一來 = 號左邊就沒有字串存在了,因此造成 test 的語法錯誤﹗ 
但是,下面這個寫法則是成立的: 
代码:
$ [ "$A" = abc ] 
$ echo $? 
1

這是因為在命令行重組後的結果為: 
[ "" = abc ] 
由於 = 左邊我們用 soft quote 得到一個空字串,而讓 test 語法得以通過... 

讀者諸君請務必留意這些細節哦,因為稍一不慎,將會導至 test 的結果變了個樣﹗ 
若您對 test 還不是很有經驗的話,那在使用 test 時不妨先採用如下這一個"法則": 
* 假如在 test 中碰到變量替換,用 soft quote 是最保險的﹗ 
若你對 quoting 不熟的話,請重新溫習第四章的內容吧... ^_^ 

okay,關於更多的 test 用法,老話一句:請看 man page 吧﹗ ^_^ 

雖然洋洋灑灑講了一大堆,或許你還在嘀咕.... 那... 那個 return value 有啥用啊?﹗ 
問得好﹗ 
告訴你:return value 的作用可大了﹗若你想讓你的 shell 變"聰明"的話,就全靠它了: 
* 有了 return value,我們可以讓 shell 跟據不同的狀態做不同的時情... 

這時候,才讓我來揭曉本章的答案吧~~~ ^_^ 
&& 與 || 都是用來"組建"多個 command line 用的: 
* command1 && command2 :其意思是 command2 只有在 RV 為 0 (true) 的條件下執行。 
* command1 || command2 :其意思是 command2 只有在 RV 為非 0 (false) 的條件下執行。 
來,以例子來說好了: 
代码:
$ A=123 
$ [ -n "$A" ] && echo "yes! it's ture." 
yes! it's ture. 
$ unset A 
$ [ -n "$A" ] && echo "yes! it's ture." 
$ [ -n "$A" ] || echo "no, it's NOT ture." 
no, it's NOT ture.

(註:[ -n string ] 是測試 string 長度大於 0 則為 true 。) 
上例的第一個 && 命令行之所以會執行其右邊的 echo 命令,是因為上一個 test 送回了 0 的 RV 值﹔ 
但第二次就不會執行,因為為 test 送回非 0 的結果... 
同理,|| 右邊的 echo 會被執行,卻正是因為左邊的 test 送回非

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -