linux學習之linux百問,不斷更新

來源:互聯網
上載者:User

1、Shell指令碼中用#表示注釋,相當於C語言的//注釋。但如果#位於第一行開頭,並且是#!(稱為Shebang)則例外,它表示該指令碼使用 後面指定的解譯器/bin/sh解釋執行

 

$ chmod +x script.sh$ ./script.sh

 

2、兩種執行Shell指令碼的方法:

$ ./script.sh$ sh ./script.sh

3、 一行中可以輸入由分號;隔開的多個命令

 

$ cd ..;ls -l

4、 只存在於當前Shell進程,用 set 命令可以顯示當前Shell進程中定義的所有變數(包括本地變數和環境變數)和函數

 

 

環境變數是任何進程都有的概念,而本地變數是Shell特有的概念。在Shell中,環境變數和本地變數的定義和用法相似。在Shell中定義或賦值一個變數:

$ VARNAME=value

注意等號兩邊都不能有空格,否則會被Shell解釋成命令和命令列參數。

一個變數定義後僅存在於當前Shell進程,它是本地變數,用export命令可以把本地變數匯出為環境變數,定義和匯出環境變數通常可以一步完成:

$ export VARNAME=value

也可以分兩步完成:

$ VARNAME=value$ export VARNAME

unset命令可以刪除已定義的環境變數或本地變數。

$ unset VARNAME

如果一個變數叫做VARNAME,用${VARNAME}可以表示它的值,在不引起歧義的情況下也可以用$VARNAME表示它的值。通過以下例子比較這兩種標記法的不同:

$ echo $SHELL$ echo $SHELLabc$ echo $SHELL abc$ echo ${SHELL}abc

注意,在定義變數時不用$,取變數值時要用$。和C語言不同的是,Shell變數不需要明確定義類型,事實上Shell變數的值都是字串,比如我們定義VAR=45,其實VAR的值是字串45而非整數。Shell變數不需要先定義後使用,如果對一個沒有定義的變數取值,則值為空白字串。

5、Shell指令碼中的單引號和雙引號一樣都是字串的界定符(雙引號下一節介紹),而不是字元的界定符。單引號用於保持引號內所有字元的字面值,即使引號內的\和斷行符號也不例外,但是字串中不能出現單引號。如果引號沒有配對就輸入斷行符號,Shell會給出續行提示符,要求使用者把引號配上對。例如:

$ echo '$SHELL'$SHELL$ echo 'ABC\(斷行符號)> DE'(再按一次斷行符號結束命令)ABC\DE

6、命令代換:`或 $()

由反引號括起來的也是一條命令,Shell先執行該命令,然後將輸出結果立刻代換到當前命令列中。例如定義一個變數存放date命令的輸出:

$ DATE=`date`$ echo $DATE

命令代換也可以用$()表示:

$ DATE=$(date)

7、

雙引號用於保持引號內所有字元的字面值(斷行符號也不例外),但以下情況除外:

  • $加變數名可以取變數的值

  • 反引號仍表示命令替換

  • \$表示$的字面值

  • \`表示`的字面值

  • \"表示"的字面值

  • \\表示\的字面值

  • 除以上情況之外,在其它字元前面的\無特殊含義,只表示字面值

$ echo "$SHELL"/bin/bash$ echo "`date`"Sun Apr 20 11:22:06 CEST 2003$ echo "I'd say: \"Go for it\""I'd say: "Go for it"$ echo "\"(斷行符號)>"(再按一次斷行符號結束命令)"$ echo "\\"\

8、啟動bash會自動執行以下指令碼:

  1. 首先執行/etc/profile,系統中每個使用者登入時都要執行這個指令碼,如果系統管理員希望某個設定對所有使用者都生效,可以寫在這個指令碼裡

  2. 然後依次尋找目前使用者主目錄的~/.bash_profile~/.bash_login~/.profile三個檔案,找到第一個存在並且可讀的檔案來執行,如果希望某個設定只對目前使用者生效,可以寫在這個指令碼裡,由於這個指令碼在/etc/profile之後執行,/etc/profile設定的一些環境變數的值在這個指令碼中可以修改,也就是說,目前使用者的設定可以覆蓋(Override)系統中全域的設定。~/.profile這個啟動指令碼是sh規定的,bash規定首先尋找以~/.bash_開頭的啟動指令碼,如果沒有則執行~/.profile,是為了和sh保持一致。

  3. 順便一提,在退出登入時會執行~/.bash_logout指令碼(如果它存在的話)。

 

9、條件測試test

 

命令test[可以測試一個條件是否成立,如果測試結果為真,則該命令的Exit Status為0,如果測試結果為假,則命令的Exit Status為1(注意與C語言的邏輯表示正好相反)。例如測試兩個數的大小關係:

$ VAR=2$ test $VAR -gt 1$ echo $?0$ test $VAR -gt 3$ echo $?1$ [ $VAR -gt 3 ]$ echo $?1

雖然看起來很奇怪,但左方括弧[確實是一個命令的名字,傳給命令的各參數之間應該用空格隔開,比如,$VAR-gt3][命令的四個參數,它們之間必須用空格隔開。命令test[的參數形式是相同的,只不過test命令不需要]參數。以[命令為例,常見的測試命令如下表所示:

[ -d DIR ] 如果DIR存在並且是一個目錄則為真
[ -f FILE ] 如果FILE存在且是一個普通檔案則為真
[ -z STRING ] 如果STRING的長度為零則為真
[ -n STRING ] 如果STRING的長度非零則為真
[ STRING1 = STRING2 ] 如果兩個字串相同則為真
[ STRING1 != STRING2 ] 如果字串不相同則為真
[ ARG1 OP ARG2 ] ARG1ARG2應該是整數或者取值為整數的變數,OP-eq(等於)-ne(不等於)-lt(小於)-le(小於等於)-gt(大於)-ge(大於等於)之中的一個

 

和C語言類似,測試條件之間還可以做與、或、非邏輯運算:

帶與、或、非的測試命令

[ ! EXPR ] EXPR可以是上表中的任意一種測試條件,!表示邏輯反
[ EXPR1 -a EXPR2 ] EXPR1EXPR2可以是上表中的任意一種測試條件,-a表示邏輯與
[ EXPR1 -o EXPR2 ] EXPR1EXPR2可以是上表中的任意一種測試條件,-o表示邏輯或

 

例如:

$ VAR=abc$ [ -d Desktop -a $VAR = 'abc' ]$ echo $?0

注意,如果上例中的$VAR變數事先沒有定義,則被Shell展開為空白字串,會造成測試條件的語法錯誤(展開為[ -d Desktop -a = 'abc' ]),作為一種好的Shell編程習慣,應該總是把變數取值放在雙引號之中(展開為[ -d Desktop -a "" = 'abc' ]):

$ unset VAR$ [ -d Desktop -a $VAR = 'abc' ]bash: [: too many arguments$ [ -d Desktop -a "$VAR" = 'abc' ]$ echo $?1

10、 case/esac

case命令可類比C語言的switch/case語句,esac表示case語句塊的結束。C語言的case只能匹配整型或字元型常量運算式,而Shell指令碼的case可以匹配字串和Wildcard,每個匹配分支可以有若干條命令,末尾必須以;;結束,執行時找到第一個匹配的分支並執行相應的命令,然後直接跳到esac之後,不需要像C語言一樣用break跳出。

#! /bin/shecho "Is it morning? Please answer yes or no."read YES_OR_NOcase "$YES_OR_NO" inyes|y|Yes|YES)  echo "Good Morning!";;[nN]*)  echo "Good Afternoon!";;*)  echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."  exit 1;;esacexit 0

使用case語句的例子可以在系統服務的指令碼目錄/etc/init.d中找到。這個目錄下的指令碼大多具有這種形式(以/etc/apache2為例):

case $1 instart)...;;stop)...;;reload | force-reload)...;;restart)...*)log_success_msg "Usage: /etc/init.d/apache2 {start|stop|restart|reload|force-reload|start-htcacheclean|stop-htcacheclean}"exit 1;;esac

啟動apache2服務的命令是

$ sudo /etc/init.d/apache2 start

$1是一個特殊變數,在執行指令碼時自動取值為第一個命令列參數,也就是start,所以進入start)分支執行相關的命令。同理,命令列參數指定為stopreloadrestart可以進入其它分支執行停止服務、重新載入設定檔或重新啟動服務的相關命令。

11、if fi

和C語言類似,在Shell中用ifthenelifelsefi這幾條命令實現分支控制。這種流程式控制制語句本質上也是由若干條Shell命令組成的,例如先前講過的

if [ -f ~/.bashrc ]; then    . ~/.bashrcfi

其實是三條命令,if [ -f ~/.bashrc ]是第一條,then . ~/.bashrc是第二條,fi是第三條。如果兩條命令寫在同一行則需要用;號隔開,一行唯寫一條命令就不需要寫;號了,另外,then後面有換行,但這條命令沒寫完,Shell會自動續行,把下一行接在then後面當作一條命令處理。和[命令一樣,要注意命令和各參數之間必須用空格隔開。if命令的參數組成一條子命令,如果該子命令的Exit Status為0(表示真),則執行then後面的子命令,如果Exit Status非0(表示假),則執行elifelse或者fi後面的子命令。if後面的子命令通常是測試命令,但也可以是其它命令。Shell指令碼沒有{}括弧,所以用fi表示if語句塊的結束。見下例:

#! /bin/shif [ -f /bin/bash ]then echo "/bin/bash is a file"else echo "/bin/bash is NOT a file"fiif :; then echo "always true"; fi

:是一個特殊的命令,稱為空白命令,該命令不做任何事,但Exit Status總是真。此外,也可以執行/bin/true/bin/false得到真或假的Exit Status。再看一個例子:

#! /bin/shecho "Is it morning? Please answer yes or no."read YES_OR_NOif [ "$YES_OR_NO" = "yes" ]; then  echo "Good morning!"elif [ "$YES_OR_NO" = "no" ]; then  echo "Good afternoon!"else  echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."  exit 1fiexit 0

上例中的read命令的作用是等待使用者輸入一行字串,將該字串存到一個Shell變數中。

此外,Shell還提供了&&和||文法,和C語言類似,具有Short-circuit特性,很多Shell指令碼喜歡寫成這樣:

test "$(whoami)" != 'root' && (echo you are using a non-privileged account; exit 1)

&&相當於“if...then...”,而||相當於“if not...then...”。&&和||用於串連兩個命令,而上面講的-a-o僅用於在測試運算式中串連兩個測試條件,要注意它們的區別,例如,

test "$VAR" -gt 1 -a "$VAR" -lt 3

和以下寫法是等價的

test "$VAR" -gt 1 && test "$VAR" -lt 3
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.