Shell 附錄

2018-10-26 16:46 更新

Shell編程學(xué)習(xí)筆記

前言

這是作者早期的 Shell 編程學(xué)習(xí)筆記,主要包括 Shell 概述、 Shell 變量、位置參數(shù)、特殊符號(hào)、別名、各種控制語(yǔ)句、函數(shù)等 Shell 編程知識(shí)。

要想系統(tǒng)地學(xué) Shell,應(yīng)該找些較系統(tǒng)的資料,例如:《Shell 編程范例》《鳥(niǎo)哥學(xué)習(xí)Shell Scripts》。

執(zhí)行 Shell 腳本的方式

范例:輸入重定向到 Bash

$ bash < ex1

可以讀入 ex1 中的程序,并執(zhí)行

范例:以腳本名作為參數(shù)

其一般形式是:

$ bash 腳本名 [參數(shù)]

例如:

$ bash ex2 /usr/meng /usr/zhang

其執(zhí)行過(guò)程與上一種方式一樣,但這種方式的好處是能在腳本名后面帶有參數(shù),從而將參數(shù)值傳遞給程序中的命令,使一個(gè) Shell 腳本可以處理多種情況,就如同函數(shù)調(diào)用時(shí)可根據(jù)具體問(wèn)題傳遞相應(yīng)的實(shí)參。

范例:以 . 來(lái)執(zhí)行

如果以當(dāng)前 Shell (以 · 表示)執(zhí)行一個(gè) Shell 腳本,則可以使用如下簡(jiǎn)便形式:

$ · ex3[參數(shù)]

范例:直接執(zhí)行

將 Shell 腳本的權(quán)限設(shè)置為可執(zhí)行,然后在提示符下直接執(zhí)行它。

具體辦法:

$ chmod a+x ex4
$ ./ex4

這個(gè)要求在 Shell 腳本的開(kāi)頭指明執(zhí)行該腳本的具體 Shell,例如 /bin/bash

#!/bin/bash

Shell 的執(zhí)行原理

Shell 接收用戶(hù)輸入的命令(腳本名),并進(jìn)行分析。如果文件被標(biāo)記為可執(zhí)行,但不是被編譯過(guò)的程序,Shell 就認(rèn)為它是一個(gè) Shell 腳本。 Shell 將讀取其中的內(nèi)容,并加以解釋執(zhí)行。所以,從用戶(hù)的觀點(diǎn)看,執(zhí)行 Shell 腳本的方式與執(zhí)行一般的可執(zhí)行文件的方式相似。

因此,用戶(hù)開(kāi)發(fā)的 Shell 腳本可以駐留在命令搜索路徑的目錄之下(通常是 /bin/usr/bin等),像普通命令一樣使用。這樣,也就開(kāi)發(fā)出自己的新命令。如果打算反復(fù)使用編好的 Shell 腳本,那么采用這種方式就比較方便。

變量賦值

可以將一個(gè)命令的執(zhí)行結(jié)果賦值給變量。有兩種形式的命令替換:一種是使用倒引號(hào)引用命令,其一般形式是: 命令表。

范例:獲取當(dāng)前的工作目錄并存放到變量中

例如:將當(dāng)前工作目錄的全路徑名存放到變量dir中,輸入以下命令行:

$ dir=`pwd`

另一種形式是:$(命令表)。上面的命令行也可以改寫(xiě)為:

$ dir=$(pwd)

數(shù)組

Bash 只提供一維數(shù)組,并且沒(méi)有限定數(shù)組的大小。類(lèi)似與 C 語(yǔ)言,數(shù)組元素的下標(biāo)由 0 開(kāi)始編號(hào)。獲取數(shù)組中的元素要利用下標(biāo)。下標(biāo)可以是整數(shù)或算術(shù)表達(dá)式,其值應(yīng)大于或等于 0 。用戶(hù)可以使用賦值語(yǔ)句對(duì)數(shù)組變量賦值。

范例:對(duì)數(shù)組元素賦值

對(duì)數(shù)組元素賦值的一般形式是:數(shù)組名[下標(biāo)]=值,例如:

$ city[0]=Beijing
$ city[1]=Shanghai
$ city[2]=Tianjin

也可以用 declare 命令顯式聲明一個(gè)數(shù)組,一般形式是:

$ declare -a 數(shù)組名

范例:訪(fǎng)問(wèn)某個(gè)數(shù)組元素

讀取數(shù)組元素值的一般格式是: ${數(shù)組名[下標(biāo)]},例如:

$ echo ${city[0]}
Beijing

范例:數(shù)組組合賦值

一個(gè)數(shù)組的各個(gè)元素可以利用上述方式一個(gè)元素一個(gè)元素地賦值,也可以組合賦值。定義一個(gè)數(shù)組并為其賦初值的一般形式是:

數(shù)組名=(值1 值2 ... 值n)

其中,各個(gè)值之間以空格分開(kāi)。例如:

$ A=(this is an example of shell script)
$ echo ${A[0]} ${A[2]} ${A[3]} ${A[6]}
this an example script
$ echo ${A[8]}

由于值表中初值共有 7 個(gè),所以 A 的元素個(gè)數(shù)也是 7 。 A[8] 超出了已賦值的數(shù)組 A 的范圍,就認(rèn)為它是一個(gè)新元素,由于預(yù)先沒(méi)有賦值,所以它的值是空串。

若沒(méi)有給出數(shù)組元素的下標(biāo),則數(shù)組名表示下標(biāo)為 0 的數(shù)組元素,如 city 就等價(jià)于 city[0]。

范例:列出數(shù)組中所有內(nèi)容

使用 *@ 做下標(biāo),則會(huì)以數(shù)組中所有元素取代。

$ echo ${A[*]}
this is an example of shell script

范例:獲取數(shù)組元素個(gè)數(shù)

$ echo ${#A[*]}
7

參數(shù)傳遞

假如要編寫(xiě)一個(gè) Shell 來(lái)求兩個(gè)數(shù)的和,可以怎么實(shí)現(xiàn)呢?為了介紹參數(shù)傳遞的用法,編寫(xiě)這樣一個(gè)腳本:

$ cat > add
let sum=$1+$2
echo $sum

保存后,執(zhí)行一下:

$ chmod a+x ./add
$ ./add 5 10
15

可以看出 5 和 10 分別傳給了 $1$2,這是 Shell 自己預(yù)設(shè)的參數(shù)順序,其實(shí)也可以先定義好變量,然后傳遞進(jìn)去。

例如,修改上述腳本得到:

let sum=$X+$Y
echo $sum

再次執(zhí)行:

$ X=5 Y=10 ./add
15

可以發(fā)現(xiàn),同樣可以得到正確結(jié)果。

設(shè)置環(huán)境變量

export一個(gè)環(huán)境變量:

$ export opid=True

這樣子就可以,如果要登陸后都生效,可以直接添加到 /etc/profile 或者 ~/.bashrc 里頭。

鍵盤(pán)讀起變量值

可以通過(guò) read 來(lái)讀取變量值,例如,來(lái)等待用戶(hù)輸入一個(gè)值并且顯示出來(lái):

$ read -p "請(qǐng)輸入一個(gè)值 : "  input ; echo "你輸入了一個(gè)值為 :" $input
請(qǐng)輸入一個(gè)值 : 21500
你輸入了一個(gè)值為 : 21500

設(shè)置變量的只讀屬性

有些重要的 Shell 變量,賦值后不應(yīng)該修改,那么可設(shè)置它為 readonly

$ oracle_home=/usr/oracle7/bin
$ readonly oracle_home

條件測(cè)試命令 test

語(yǔ)法:test 表達(dá)式如果表達(dá)式為真,則返回真,否則,返回假。

范例:數(shù)值比較

先給出數(shù)值比較時(shí)常見(jiàn)的比較符:

-eg =;-ne !=;-gt >;-ge >=;-lt <;-le <=

$ test var1 -gt var2

范例:測(cè)試文件屬性

文件的可讀、可寫(xiě)、可執(zhí)行,是否為普通文件,是否為目錄分別對(duì)應(yīng):

-r; -w; -x; -f; -d

$ test -r filename

范例:字符傳屬性以及比較

串的長(zhǎng)度為零:-z; 非零:-n,如:

$ test -z s1

如果串 s1 長(zhǎng)度為零,返回真。

范例:串比較

相等"s1"="s2"; 不相等 "s1"!="s2"

還有一種比較串的方法(可以按字典序來(lái)比較):

$ if [[ 'abcde' < 'abcdf' ]]; then  echo "yeah,果然是誒"; fi
yeah,果然是誒

整數(shù)算術(shù)或關(guān)系運(yùn)算 expr

可用該命令進(jìn)行的運(yùn)算有:

算術(shù)運(yùn)算:+ - * / %;邏輯運(yùn)算:= ! < <= > >=

如:

$ i=5;expr $i+5

另外,bc 是一個(gè)命令行計(jì)算器,可以進(jìn)行一些算術(shù)計(jì)算。

控制執(zhí)行流程命令

范例:條件分支命令 if

if 命令舉例:如果第一個(gè)參數(shù)是一個(gè)普通文件名,那么分頁(yè)打印該文件;否則,如果它為目錄名,則進(jìn)入該目錄并打印該目錄下的所有文件,如果也不是目錄,那么提示相關(guān)信息。

if test -f $1
then
    pr $1>/dev/lp0
elif
    test-d $1
then
    (cd $1;pr *>/dev/lp0)
else
    echo $1 is neither a file nor a directory
fi

范例:case 命令舉例

case 命令是一個(gè)基于模式匹配的多路分支命令,下面將根據(jù)用戶(hù)鍵盤(pán)輸入情況決定下一步將執(zhí)行那一組命令。

while [ $reply!="y" ] && [ $reply!="Y" ]                         #下面將學(xué)習(xí)的循環(huán)語(yǔ)句
do
    echo "\nAre you want to continue?(Y/N)\c"
    read reply             #讀取鍵盤(pán)
    case $replay in
        (y|Y) break;;         #退出循環(huán)
        (n|N) echo "\n\nTerminating\n"
              exit 0;;
            *) echo "\n\nPlease answer y or n"
            continue;       #直接返回內(nèi)層循環(huán)開(kāi)始出繼續(xù)
    esac
done

范例:循環(huán)語(yǔ)句 while, until

語(yǔ)法:

while/until 命令表1
do
    命令表2
done

區(qū)別是,前者執(zhí)行命令表 1 后,如果退出狀態(tài)為零,那么執(zhí)行 do 后面的命令表 2,然后回到起始處,而后者執(zhí)行命令表 1 后,如果退出狀態(tài)非零,才執(zhí)行類(lèi)似操作。例子同上。

范例:有限循環(huán)命令 for

語(yǔ)法:

for 變量名 in 字符串表
do
    命令表
done

舉例:

FILE="test1.c myfile1.f pccn.h"
for i in $FILE
do
    cd ./tmp
    cp $i $i.old
    echo "$i copied"
done

函數(shù)

現(xiàn)在來(lái)看看 Shell 里頭的函數(shù)用法,先看個(gè)例子:寫(xiě)一個(gè)函數(shù),然后調(diào)用它顯示 Hello, World!

$ cat > show
# 函數(shù)定義
function show
{
    echo $1$2;
}
H="Hello,"
W="World!"
# 調(diào)用函數(shù),并傳給兩個(gè)參數(shù)H和W
show $H $W

演示:

$ chmod 770 show
$./show
Hello,World!

看出什么蹊蹺了嗎?

$ show $H $W

咱們可以直接在函數(shù)名后面跟實(shí)參。

實(shí)參順序?qū)?yīng)“虛參”的 $1,$2,$3……

注意:假如要傳入一個(gè)參數(shù),如果這個(gè)參數(shù)中間帶空格,怎么辦? 先試試看。

來(lái)顯示 Hello World (兩個(gè)單詞之間有個(gè)空格)

function show
{
    echo $1
}
HW="Hello World"
show "$HW"

如果直接 show $HW,肯定不行,因?yàn)?$1 只接受到了 Hello,所以結(jié)果只顯示 Hello,原因是字符串變量必須用 " 包含起來(lái)。

后記

感興趣的話(huà)繼續(xù)學(xué)習(xí)吧!

還有好多強(qiáng)大的東西等著呢,比如 cut,expr,sed,awk 等等。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)