shell十三問總結

來源:互聯網
上載者:User

標籤:

我們知道電腦的硬體資源比如磁碟,IO,記憶體都是由軟體來統一管理的,這類特殊的軟體就是常說的作業系統,windows在底層的資源控制基礎上構建了自己的介面,非常適合使用,只需要到處點點就能完成我們需要的功能。這是一種控制資源的方式,同時也可以使用command的方式來操作底層的資源。liunx中最重要的部分是它的核心,核心管理著系統的資源,同時也提供給我們操作核心的介面,就是我們經常用到的shell(殼),主流的shell有以下幾種:

sh:

                burne shell (sh)
                burne again shell (bash)
        csh:
                c shell (csh)
                tc shell (tcsh)

                korn shell (ksh)

接觸比較多的是bash和ksh,幾種不同的shell功能大體相似,當然也各有特點。

一般給非管理使用者顯示的是$,管理員顯示的是root。linux下的分行符號(按下enter鍵)用CR表示,當遇到CR時,shell解譯器會去解釋CR前面的command line,解釋命令列是先按照IFS去分割命令列,然後對其中的元字元進行處理,比如:echo $A 其中A的值為hello,按照IFS(預設為tab,newline,space)拆解為echo和$A然後對元字元$進行解釋,取A變數的值,最後輸出hello到螢幕。

一、echo

echo命令是我們經常需要用到的輸出命令,可以查看參數的值,其中提供了幾個參數,能夠實現不同的效果,比如echo -n就是取消末尾的分行符號,可以在環境上試試輸出echo -n "a" 和echo "a"有什麼不同。如果我們想在預設再增加一個換行可能會想到echo "a\n",這是行不通的,echo預設執行的是-E參數,表示不去解釋反斜線的字元轉換,因此需要開啟\功能,需要使用-e參數,如下:echo -e "a\n"。

二、雙引號""和單引號‘‘

在shell中雙引號和單引號的作用是不同的,shell中的字元可以分為兩種,一種是一般字元,一種是元字元,比如$是一種元字元,當執行到元字元的時候shell會去做相應的動作,比如echo $A就是列印變數A的值,但是如果我們想列印“$A”那麼應該怎麼實現呢,答案就是使用單引號,echo ‘$A‘,單引號中的所有元字元都會被當做普通的字元來處理,那麼雙引號又有什麼不同呢,雙引號會關閉大部分的元字元處理,但是有少部分還是會當做元字元來解釋,比如$符號,另外還有一種關閉元字元的做法是在元字元前加/反斜線。

三、var=value和export

嚴格來說在當前shell中定義的的變數均為本地變數,只有export後才會成為環境變數,供後面的命令使用,export命令的詳細解釋以後會提到。

四、exec和source

執行shell的時候經常用到source *.sh,實際上我們執行*.sh指令碼的時候,會產生一個subshell進程來執行,並且該子進程的環境變數和父進程的環境變數不是共用的,因此假如我們定義cd /home/a/b/d命令在test.sh指令碼中,並且在/home/a下面執行test.sh,實際上目錄並不會切換到/home/a/b/d下,就是這個原因。那麼如何才能執行test.sh使得目錄切換,shell提供了兩種方式來阻止產生subshell進程執行指令碼,source和exec,這兩個命令會在當前的shell進程中完成指令碼的調用。那麼這兩種方式的調用又有什麼區別呢?看下面的一個例子:

1.sh

#!/bin/bashA=Becho "PID of 1.sh before exec/source/fork:$$"export Aecho "1.sh :\$A is $A"case $1 in        exec)                echo "using exec..."                exec ./2.sh ;;        source)                echo "using source"                . ./2.sh ;;        *)                echo "using fork"                ./2.sh ;;esacecho "PID of 1.sh after exec/source/fork:$$"echo "1.sh:\$A is $A"

2.sh

#!/bin/bashecho "PID for 2.sh is: $$"echo "2.sh get \$A=$A form 1.sh"A=Cexport Aecho "2.sh:\$A is $A"

執行./1.sh fork後的結果:

PID of 1.sh before exec/source/fork:18885
1.sh :$A is B
using fork
PID for 2.sh is: 18886
2.sh get $A=B form 1.sh
2.sh:$A is C
PID of 1.sh after exec/source/fork:18885
1.sh:$A is B

執行./1.sh exec後的結果:

PID of 1.sh before exec/source/fork:20952
1.sh :$A is B
using exec...
PID for 2.sh is: 20952
2.sh get $A=B form 1.sh
2.sh:$A is C

執行./1.sh source後的結果:a

PID of 1.sh before exec/source/fork:26519
1.sh :$A is B
using source
PID for 2.sh is: 26519
2.sh get $A=B form 1.sh
2.sh:$A is C
PID of 1.sh after exec/source/fork:26519
1.sh:$A is C

下面逐一分析列印的結果:

預設的fork執行,會產生一個子進程來執行shell指令碼,其中父進程中的export效果會傳遞到子進程,但是子進程中的export效果並不會傳遞給父進程,因此export命令的效果是單向的,從父進程傳遞子進程。

exec和source執行並不會產生子進程,而是在當前進程執行指令碼,不同點是exec會終止當前的指令碼執行,當子指令碼執行完畢後,整個執行過程就算完畢了。

五、()和{}的區別

這裡要引入一個命令組的概念,就像是其他語言中的函數,()和{}的不同是()是在子shell中執行,{}是在本shell中執行,說到這裡不得不提出一個概念,函數,在shell中定義函數的方式有兩種,一種是function_name{},還有一種是function_name (){}。

六、$(())、${}和$()的區別

在bash中,$()和``都是用作命令替換,命令替換和之前的變數替換的概念有些類似,比如dir=$(pwd),首先pwd的執行結果會賦值給變數dir,${}的作用是變數替換,比如A=B;echo ${A},實際上在這裡也可以直接echo $A,但是假如寫成echo $AA,則shell是不識別的,因此${}起到一個邊界的作用,但是如果你只認為${}只是起到邊界的作用,那就太小瞧它了。

假設有變數file=/dir1/dir2/dir3/my.file.txt

我們可以用${}進行不同的變數替換得到不同的值。

${file#*/}:去掉第一個/及其左邊的所有字元,結果為dir1/dir2/dir3/my.file.txt

${file##*/}去掉最後一個/及其左邊的所有字元,結果為my.file.txt

${file%/*}去掉最後一個/及其右邊的所有字元,結果為/dir1/dir2/dir3

${file%%/*}:拿掉第一個 / 及其右邊的字串:(空值)
#是去掉左邊,%是去掉右邊,一個是最短匹配,兩個是最長相符

${file:0:5} 結果為從第0個開始向右取5個字元/dir1

因此${file:offset:length}從offset開始向右取length個字元

${file/dir/path}將第一個dir替換為path,結果為/path1/dir2/dir3/my.file.txt

${file//dir/path}將所有的dir都替換為path。

上面的是字元的替換,還可以根據當前的值是否為空白來做替換,如下:

${file-myfile.txt}如果file未定義則輸出myfile.txt

${file:-myfile.txt}如果file未定義或者為定義為空白則輸出myfile.txt

${file+myfile.txt}如果file有定義則不論是否為空白,都輸出myfile.txt

${file:+myfile.txt}如果file不為空白,則輸出myfile.txt

${file=myfile.txt}如果file未定義則輸出myfille.txt同時賦值file為myfile.txt

${file:=myfile.txt}如果file未定義或者為空白,則輸出myfile.txt


${#file}輸出file變數的長度

順便再來介紹一下bash中的數組array

數組的定義類似:A=(a b c d e)中間用空格分割

如果要得到這個數組的內容,可以使用${A[@]}或者${A[*]}

最後再來看下$(())的用途,$(())方便我們做整數運算,比如a=1;b=2;echo $((a+b))輸出為3。$(())為我們做比較和運算提供了類C語言的風格。

七、[email protected]和$*的差別

比如我們有個sh指令碼名稱為test.sh,它可以接受參數,如下 test.sh a b c,獲得外部參數的方式為$1 $2 $3分別擷取a b c,如果要擷取指令碼身的名稱則使用$0。注意指令碼中定義的函數也可以接收參數同樣可以使用$1...這種方式擷取傳入的參數。不同的時$0不是函數的名稱而是最外面指令碼的名稱。

$10表示的並不是擷取第十個參數,而是擷取第一個參數後面再加上字串0,因此如果要擷取第十個參數可以使用${10},或者使用shift命令,shift 1為取消第一個參數($0)排除,shift 5為取消前5個參數。

再介紹一個參數$#表示擷取傳入的參數總數,比如test.sh one two three 則$#為3。

如果要擷取所有的參數則可以使用[email protected],比如test.sh one two three則擷取到三個word,而$*是將參數當做一個整體。

八、&&和||的差別

在介紹$$和||之前先來瞭解一個新的概念,return value,在執行command或者function的時候都會傳值會父進程,我們可以使用$?來擷取這個最新的返回值,return value只有兩種狀態,0的話為真,非0的話為假,比如:

假設myfile.txt存在,而a.txt不存在,ls a.txt後再echo $?為非0,如果ls myfile.txt則為0。可以使用test expersion或者[ expersion ]來測試返回值。不過我更習慣使用[]這種文法。

接下來就可以看看$$和||的差別了,command1 && command2表示如果command1命令返回真則執行command2。command1 || command2表示,如果command1返回假則執行command2。

九、<和>

大概存在三種FD(檔案描述符),分別為0標準輸入,1標準輸出,2錯誤輸出,>表示標準輸出重新導向與1>相同。

2>&1表示把標準錯誤輸出重新導向到標準輸出。

&>file表示把標準輸出和標準錯誤輸出重新導向到檔案file中。

2>&-表示將標準錯誤輸出關閉

>/dev/null 2>&1表示將標準錯誤輸出綁定到標準輸入並且標準輸入重新導向到/dev/null,也即什麼都不會輸出

十、case和if

有時候需要根據當前的值來執行不同的邏輯,if在這裡就派上了用場,標準的if用法為:

if comd1;then

comd2

elif comd3;then

comd4

else 

comd5

fi

如果then後面不想跑任何命令可以使用:這個null command來替代。

如果條件比較多並且為字串則可以使用另外一種文法,case

case "$1" in

start)

start

;;

stop)

stop

;;

restart|reload)

restart

;;

*)

exit 1

esac

十一、for、while與until

loop是非常基本的一種邏輯控制,所有的語言都提供了自己的迴圈控制語句

for loop從一個清單列表中讀取值,依次做處理:

for var in one two three four five

do

...

done

下面給出一個累計變數的語句:

for ((i=1;i<=10;i++))

do

...

done

如果改為while實現則如下:

num=1

while [ $num -le 10 ];do

...

done

-le表示小於等於

while是在條件為true時進入迴圈,until則相反,是在條件為false時進入迴圈。

同樣迴圈中也有break和continue關鍵字,和java等其他語言的用法是一樣的,就不做解釋了。

上面就是shell十三問的大體內容,有些內容並沒有涉及到,後續會對一些比較常用的命令比如grep,sed,awk等進行簡單的講解。

shell十三問總結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.