鍍金池/ 教程/ Linux/ shell 學習二十六天---變量與算數(shù)
shell 學習四十五天---xargs
shell學習第三天
shell 學習十五天---join 連接字段
shell 學習第二天
shell 學習四十三天---臨時性文件的建立與使用
shell 學習第六天---小結(jié)
shell 學習三十三天---關(guān)于重定向
shell 學習二十九天---循環(huán)
shell 學習二十四天---提取開頭或結(jié)尾數(shù)行
shell 學習第十天---sed 查找與替換
shell 學習第十一天---sed 正則的精確控制
shell 學習三十天---break,continue,shift,getopts
shell 學習---小結(jié)
shell 學習三十一天---函數(shù)問題
shell 學習第四天---華麗的 printf 輸出
shell 學習三十五天---波浪號展開與通配符
shell 學習十九天---文本塊排序
shell 學習十二天---行與字符串
shell 學習二十一天---重新格式化段落
shell 學習十八天---文本排序
shell 學習十三天---sed 案例分析
shell 學習四十一天---列出文件 ls 和 od 命令
shell 學習十七天---awk 命令
shell 學習三十六天---命令替換
shell 學習十六天---join 練習
shell 學習三十二天---read 讀取一行
shell 學習二十二天---計算行數(shù),字數(shù)以及字符數(shù)
shell 學習小總結(jié)---本章小結(jié)
shell 學習第八天---擴展正則表達式(ERE)
shell 學習四十二天---使用 touch 更新文件時間
shell 學習二十八天---case 語句
shell 學習三十九天---內(nèi)建命令
shell 學習第一天
shell 學習三十四天---printf 詳解
shell 學習二十六天---變量與算數(shù)
shell 學習三十八天---執(zhí)行順序和 eval
shell 學習四十四天---尋找文件
shell 學習二十五天---神器的管道符
shell 學習十四天---使用 cut 選定字段
shell 學習第五天---基本的I/O重定向
shell 學習四十天---awk 的驚人表現(xiàn)
shell 學習二十天---sort 的其他內(nèi)容以及 uniq 命令
shell 學習二十三天---打印
shell 學習第九天---分組
shell 學習四十八天---文件校驗和匹配
shell 學習二十七天---退出狀態(tài)和 if 語句
shell 學習四十七天---文件比較 cmp,diff,patch
shell 學習第七天---基礎(chǔ)正則表達式(BRE)
shell 學習四十六天---文件系統(tǒng)的空間信息 df 和 du 命令
shell 學習三十七天---引用
shell 學習小結(jié)

shell 學習二十六天---變量與算數(shù)

shell 腳本與函數(shù)還有位置參數(shù)的功能;傳統(tǒng)的說法應(yīng)該是”命令行參數(shù)”;
shell 為內(nèi)嵌算數(shù)提供了一種標記法,稱為算數(shù)展開.shell 回對$((...))里的算符表達式進行計算,再將計算后的結(jié)構(gòu)放回到命令的文本內(nèi).
有兩個相似的命令提供變量的管理,一個是 readonly,它可以使變量稱為只讀模式;而賦值給它們是被禁止的.在 shell 程序中,這是創(chuàng)建符號常量的一個好方法:
days_per_week=7 賦值
readonly days_per_week 設(shè)為只讀模式

export,readonly
語法:
export name[=word]...
export -p
readonly name[=word]...
readonly =p
用途:
export 用于修改或打印環(huán)境變量,readonly 則使得變量不得修改.

主要選項:
-p:打印命令的名稱以及所有被到處(只讀)變量的名稱與值,這種方式可使得 shell 重新讀取輸出以便重新建立環(huán)境(只讀設(shè)置).
行為模式:
使用-p 選項,這兩條命令都會分別打印他們的名稱以及被到處的或只讀的所有變量.
較常見的命令是 export,用法是將變量放進環(huán)境變量里.環(huán)境是一個名稱與值的簡單列表,可供所有執(zhí)行中的程序使用.新的進程會從父進程繼承環(huán)境,也可以在建立新的紫禁城之前修改它.export 命令可將新變量添加到環(huán)境中:
PATH=$PATH:/usr/local/bin 更新 PATH
export PATH 導出它
使用 export -p 命令可以顯示當前環(huán)境
變量可以添加到程序環(huán)境中,但是對 shell 或接下來的命令不會一直有效:將該變量賦值,置于命令名稱與參數(shù)前即可:
PATH=/bin:/usr/bin awk ‘...’ file1 file2
這個 PATH 值只對后面 awk 起作用,其他命令將使用系統(tǒng) PATH.
使用 env 命令顯示所有環(huán)境變量.
unset 命令從執(zhí)行中的 shell 中刪除變量與函數(shù).
案例:
清除環(huán)境變量的值使用 unset 命令.如果未定義指定值,則該變量值將被設(shè)為 NULL.
首先使用命令export TEST=”test”來增加一個環(huán)境變量
接著使用命令env | grep TEST,得到結(jié)果 TEST=test
然后使用命令unset $TEST 刪除環(huán)境變量 TEST
最后使用命令env | grep TEST命令,該命令不會有輸出,說明成功的刪除了.
其中 unset 還可以通過添加-f選項刪除指定的函數(shù).
unset 的行為模式
如果沒有提供選項,則參數(shù)將視為變量名稱,并告知變量已刪
除,如果使用-f 選項,參數(shù)則被視為函數(shù)名稱,并刪除函數(shù).

注意:myvar=賦值并不會將 myvar 刪除,只不過試講其設(shè)為 null 字符串.相對的:unset myvar 完全刪除它.這一差異在于”是變量設(shè)置”以為”是變量設(shè)置,但非 null”展開.

參數(shù)展開

var =”hello,world”  
echo ${var}  
hello,world  

其實這里說的參數(shù)(parameter)不就是我們通常說的變量(variable)么? 嗯。。其實大部分時候這倆名詞的意思基本等同。只不過在 Shell 中 parameter(參數(shù))是 variable(變量)的超集: 變量名不能以數(shù)字開頭,而參數(shù)名可以。比如說$1 就表示命令行傳入的第一個參數(shù)。
參數(shù)展開是 shell 提供變量值在程序中使用的過程:例如,作為新變量的值,或是作為命令行的部分或全部參數(shù).最簡單的形式如下所示:
reminder =”Time to go to the dentist” 將值存儲在 reminder 中
sleep 120 等待兩分鐘
echo $reminder 顯示信息
在 shell 下,有更復雜的形式可用于更特殊的情況.這些形式都是將變量名稱括在花括號里(${variable}),然后再增加額外的語法以告訴 shell 該做些什么.花括號本身也是很好用的,當你需要在變量名稱之后馬上跟著一個可能會解釋為名稱一部分的字符時,他就派上用場了:

reminder =”Time to go to the dentist” 將值存儲在reminder中 sleep 120 等待兩分鐘 echo ${reminder} 顯示信息

警告:默認情況下,未定義的變量會展開為 null(空的)字符串.程序隨便亂寫,就可能會導致災難發(fā)生:
rm -rf /$MYPROGRAM 如果未設(shè)置 MYPROGRAM,就會有大災難發(fā)生了,所以在寫 程序時一定要小心.

展開運算符

第一組字符串處理運算符用來測試變量的存在狀態(tài),且為在某種情況下的允許默認值的替換.
替換運算符

運算符

替換

${varname:=word}

如果varname存在且不是null,則返回它的值;否則,設(shè)置它為word,并返回其值

用途:如果變量未定義,則返回默認值.

范例:如果?count未定義,則?echo?${count:-0}的值為0

${varname:word}

如果varname存在且不是null,則返回它的值;否則,設(shè)置它為word,并返回其值.

用途:如果變量未定義,則設(shè)置變量為默認值.

范例:如果count未定義,echo${count:=0}輸出為0

${varname:?message}

如果varname存在且非null,則返回它的值;否則,顯示varname:message,并退出當前的命令或腳本.省略message會出現(xiàn)默認信息parameter?null?or?not?set.注意,在交互式shell下不需要退出(在不同的shell間會有不同的行為,用戶需自行注意).

用途:為了捕捉由于變量未定義所導致的錯誤.

范例:${count:?”undefined”}將顯示:count:undefined!,且如果count未定義,則退出

${varname:+word}

如果varname存在且非null,則返回word;否則,返回null.

用途:未測試變量的存在.

如果:如果count已定義,${count:+1}返回1(也就是真)

該表中每個運算符內(nèi)的冒號(:)都是可選的.如果省略冒號,則將每個定義的”存在且非 null”部分改為”存在”,也就是說,運算符僅用于測試變量是否存在.

模式匹配運算符

運算符

替換

:${path#/*/}

結(jié)果:tolstoy/mem/long.file.name

:${variable##pattern}

如果模式匹配于變量值的開頭處,則刪除匹配的最長部分,并返回剩下的部分.

:${path##/*/}

結(jié)果:long.file.name

:${path%.*}

結(jié)果:/home/tolstoy/mem/long.file

:${variable%pattern}

如果模式匹配于變量值的結(jié)尾處,則刪除匹配的最短部分,并返回剩下的部分.

:${variable%%pattern}

如果模式匹配于變量值的結(jié)尾處,則刪除匹配的最長部分,并返回省下的部分

:${path%%.*}

結(jié)果:/home/tolstoy/mem/long

案例分析:${parameter#word}或{parameter##word}
作用:從 parameter 頭部開始匹配 word,并刪除成功匹配的部分.在構(gòu)造 word 時可以使用””表示任意長度的字符,”?”表示單位長度字符,并可用形如”[a-c]”的方式制定匹配”abc”中的任意字符.
另外,”#”和”##”的區(qū)別在于前置是匹配最短,而后者是最長匹配;實際上就是正則表達式中的”懶惰”和”貪婪”的概念.
var=br1br2ead
```echo ${var$$
br} 輸出:2ead echo ${var#br} 輸出:1br2ead 案例: ${parameter%word}或${parameter%%word} 作用:與前例相似,唯一不同的是從$parameter 的為不開始匹配. var="La.Maison.en.Petits.Cubes.avi" echo ${var%.} 輸出:La.Maison.en.Petits.Cubes echo ${var%%.}```
輸出:La
分析:匹配案例中的”.”時,shel l會從$var 的尾部開始查找”.”,如果是最短匹配(echo ${var%.
}),則會找到第一個”.”就停止,否則(echo ${var%%.*})會一直找到最后一個”.”才停止.可以看到,這種用法可以分方便的去掉文件后綴,從而得到文件名.

使用${#variable}可以獲得 variable 的長度:
案例:variable=qwertyuiop;
echo ${#variable}
輸出:10
記憶:

匹配的是前面,因為數(shù)字正負號總是置于數(shù)字之前;%匹配的是后面,因為百分比符號總是更在數(shù)字的后面.

這里用到了兩種匹配模式://,匹配任何位于兩個斜杠之間的元素;.,匹配點號之后接著的任何元素.

位置參數(shù)

所謂的位置參數(shù),指的是 shell 腳本的命令行參數(shù);同時也表示 zaishell 函數(shù)內(nèi)的函數(shù)參數(shù),他們的名稱是以單個的整數(shù)來命名.當整數(shù)大于9時,就應(yīng)該以花括號括起來:
echo frist arg is $1
echo tenth arg is ${10}
也可以將其與模式匹配運算符結(jié)合,應(yīng)用到位置參數(shù):
filename=${1:-/dev/tty} 如果給定參數(shù)則使用它,如無參數(shù)則使用/dev/tty
接下來的特殊”變量”提供了對傳遞的參數(shù)的總數(shù)的訪問,以及一次對所有參數(shù)的訪問:
$# : 提供傳遞到 shell 腳本或函數(shù)的參數(shù)總是.當你是為了處理選項和參數(shù)而建立循環(huán)時,它會很有用.舉例:

while [ $# !=0 ] 以 shift 逐漸減少$#,循環(huán)將會終止  
do  
case $1 in  
... 處理第一個參數(shù)  
esac  
shift 已開第一個參數(shù)  
done  

$*,$@ : 以此表示所有的命令行參數(shù).著兩個參數(shù)可用來把命令行參數(shù)傳遞給腳本或函數(shù)所執(zhí)行的程序.

“$” : 將所有命令行參數(shù)視為單個字符串.等同于”$1 $2 ...” $IFS 的第一個字符用來作為分隔符,衣服個不同的值來建立字符串.案例: printf “他和 arguments were %s\n” “$

“$@” : 將所有的命令韓參數(shù)視為單獨的而個體,就業(yè)就單獨字符串.等同于”$1” “$2” ....這是將參數(shù)傳遞給其他程序的最佳凡是,因為他會保留所有的內(nèi)嵌在每個參數(shù)里的任何空白.案例:
lpr “$@” 現(xiàn)實每一個文件
shift 命令是用來”截去”來自列表的位置參數(shù),由左開始.一旦執(zhí)行 shift,$1 的初值會永遠消失,取而代之的是$2 的舊值.$2 的值變成$3 的舊值,依次類推.$#的值會逐次減一.shift 也可使用一個可選的參數(shù),也就是要位移的參數(shù)的計數(shù).單純的 shift 等同于 shift 1.案例:
set -- hello “hi there” greetings 結(jié)束選項部分,自 hello 開始新的參數(shù)
echo $# 顯示計數(shù)值

for i in $* 循環(huán)處理每一個參數(shù)
> do echo i is $i
> done
輸出:
i is hello
i is hi
i is there
i is greeting
注意,內(nèi)嵌的空白已消失
使用命令:for i in $@ 在沒有雙引號的額情況下,$@和$得到的結(jié)果一樣
> do echo i is $i
> done
加了雙引號 for i in “$
” $*表示一個字符串
> do echo i in $i
> done
輸出:
i in hello hi there greeting
加了雙引號 for i in “$@” $@保留真正的參數(shù)值
輸出:
i in hello
i in hi there
i in greeting
使用命令 shift 截去第一個參數(shù)
echo there are now $# arguments
輸出:there are now 2arguments 證明第一個參數(shù)已經(jīng)消失
使用命令:
for i in “$@”
輸出為:
i in hi there
i in greeting

特殊變量

POSIX 中的內(nèi)置變量

變量

意義

#

表示變量的個數(shù),常用于循環(huán)

@

當前命令行所有參數(shù),置于雙引號中,表示個別命令

*

當前命令行所有參數(shù).置于雙引號中,表示將命令行所有參數(shù)當做一個單獨參數(shù)

-(連字號)

在引用數(shù)給予shell的選項

?

表示上一個命令退出的狀態(tài)

$

表示當前進程編號

0

表示當前進程名稱

!

表示最近一個后臺命令的進程編號

HOME

表示當前用戶的根目錄

IFS

表示內(nèi)部的字符分隔符

LANG

當前locale默認名稱

PATH

環(huán)境變量

PPID

父進程編號

PWD

當前工作目錄

特殊變量$$可在編寫腳本時用來建立具有唯一性的文件名(多半是臨時的),這是根據(jù) shell 的進程編號建立文件名.不過系統(tǒng)中還有一個 mktemp 也能做同樣的事情.

算數(shù)展開

shell 的算數(shù)運算符與C語言里的差不多,優(yōu)先級與順序也相同.

運算符

意義

順序

++?--

增加以減少,可前置也可放在結(jié)尾

由左至右

+?-?!?~

一元的正好與符號;邏輯與位的取反

由右至左

*?/?%

乘?除?取余

由左至右

+?-

加?減

由左至右

?<<?>>

向左位移,向右位移

由左至右

<?<=?>?>=

比較

由左至右

==?!=

相等不相等

由左至右

&

位的AND

由左至右

^

韋德Exclusive?OR

由左至右

|

位的OR

由左至右

&&

邏輯的AND

由左至右

||

邏輯的OR

由左至右

?:

條件表達式

由右至左

=?+=?-=?*=?/=&=?^=?<<=?>>=?|=

賦值運算符

由右至左

該表的運算符的優(yōu)先級由高排列至最低.
可利用圓括號將子表達式語句括起來.像 C 一樣:關(guān)系運算符(<,<=,>,>=,==與!=)產(chǎn)生數(shù)字結(jié)果中,1 為真,0 為假.
例如:$((3>2))的值為 1;echo $(((3>2)||(4<=1)))也為 1,因為著兩個子表達式里有一個為真.
對邏輯的 AND 與 OR 運算符而言,任何非 0 值函數(shù)都為真:
echo $((3&&4)) 3 與 4 都為”真”
++和--運算符不用說了.++與--運算符是可選的;實際上,所有支持 ${{...}}的 shell,都可以讓用戶在提供變量名稱時,無須前置$符號.