天天看點

Shell 學習筆記上面中的 #! 是一種約定标記, 它可以告訴系統這個腳本需要什麼樣的解釋器來執行;參數:-a,表示處理多個路徑;-s, 用于去掉指定的檔案的字尾名;format-string為雙引号單引号與雙引号效果一樣沒有引号也可以輸出格式隻指定了一個參數,但多出的參數仍然會按照該格式輸出,format-string 被重用如果沒有 arguments,那麼 %s 用NULL代替,%d 用 0 代替如果以 %d 的格式來顯示字元串,那麼會有警告,提示無效的數字,此時預設置為 0

先說明以下内容來自: http://c.biancheng.net/cpp/shell/ ,C語言中文網,請大家支援原作,點選連結檢視。

我寫下來隻是作為筆記,如果侵權,請留言,立馬删除。

Shell是一種腳本語言,那麼,就必須有解釋器來執行這些腳本,常見的腳本解釋器有:

bash:是Linux标準預設的shell。bash由Brian Fox和Chet Ramey共同完成,是BourneAgain Shell的縮寫,内部指令一共有40個。

sh: 由Steve Bourne開發,是Bourne Shell的縮寫,sh 是Unix 标準預設的shell。

另外還有:ash、 csh、 ksh等。

常見的程式設計語言分為兩類:一個是編譯型語言,如:c/c++/java等,它們遠行前全部一起要經過編譯器的編譯。另一個解釋型語言,執行時,需要使用解釋器一行一行地轉換為代碼,如:awk, perl, python與shell等。

Shell 經過了POSIX的标準化,是以它是可以在不同的linux系統上進行移植。

關于注釋的問題: 在shell中使用#進行注釋,注意,sh裡面沒有多行注釋,隻能每一行加一個#号;

第一個shell腳本程式:

#!/bin/bash

上面中的 #! 是一種約定标記, 它可以告訴系統這個腳本需要什麼樣的解釋器來執行;

echo “Hello, world!”

變量:

定義變量:

country=“China”

Number=100

注意: 1,變量名和等号之間不能有空格;

2,首個字元必須為字母(a-z,A-Z)。

3, 中間不能有空格,可以使用下劃線(_)。

4, 不能使用标點符号。

5, 不能使用bash裡的關鍵字(可用help指令檢視保留關鍵字)。

使用變量:

隻需要在一個定義過的變量前面加上美元符号 $ 就可以了, 另外,對于變量的{} 是可以選擇的, 它的目的為幫助解釋器識别變量的邊界.

country=“China”

echo $country

echo ${country}

echo “I love my ${country}abcd!”

#這個需要有{}的;

重定義變量: 直接把變量重新像開始定義的那樣子指派就可以了:

country=“China”

country=“ribenguizi”

隻讀變量: 用 readonly 指令 可以把變量字義為隻讀變量。

readonly country=“China”

#或

country=“China”

readonly country

删除變量: 使用unset指令可以删除變量,但是不能删除隻讀的變量。用法:

unset variable_name

變量類型

運作shell時,會同時存在三種變量:

  1. 局部變量

    局部變量在腳本或指令中定義,僅在目前shell執行個體中有效,其他shell啟動的程式不能通路局部變量。

  2. 環境變量

    所有的程式,包括shell啟動的程式,都能通路環境變量,有些程式需要環境變量來保證其正常運作。必要的時候shell腳本也可以定義環境變量。

  3. shell變量

    shell變量是由shell程式設定的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運作

特殊變量:

image

$* 和 [email protected] 的差別為: $* 和 [email protected] 都表示傳遞給函數或腳本的所有參數,不被雙引号(" “)包含時,都以”$1" “ 2 " … " 2" … " 2"…"n” 的形式輸出所有參數。但是當它們被雙引号(" “)包含時,”$*" 會将所有的參數作為一個整體,以"$1 $2 … n " 的 形 式 輸 出 所 有 參 數 ; " n"的形式輸出所有參數;" n"的形式輸出所有參數;"@" 會将各個參數分開,以"$1" “ 2 " … " 2" … " 2"…"n” 的形式輸出所有參數。

$? 可以擷取上一個指令的退出狀态。所謂退出狀态,就是上一個指令執行後的傳回結果。退出狀态是一個數字,一般情況下,大部分指令執行成功會傳回 0,失敗傳回 1。

Shell中的替換

轉義符:

在echo中可以用于的轉義符有:

image

使用 echo 指令的 –E 選項禁止轉義,預設也是不轉義的; 使用 –n 選項可以禁止插入換行符;

使用 echo 指令的 –e 選項可以對轉義字元進行替換。

另外,注意,經過我的實驗,得到:

echo “\” #得到

echo -e “\” #得到 \

echo “\\” #得到 \

echo -e “\” #得到

指令替換:

它的意思就是說我們把一個指令的輸出指派給一個變量,方法為把指令用反引号(在Esc下方)引起來. 比如:

directory=

pwd

echo $directory

變量替換:

可以根據變量的狀态(是否為空、是否定義等)來改變它的值.

image

Shell運算符

算數運算符:

原生bash不支援簡單的數學運算,但是可以通過其他指令來實作,例如 awk 和 expr. 下面使用expr進行; expr是一款表達式計算工具,使用它可以完成表達式的求值操作;

image

比如:

複制代碼

a=10

b=20

expr $a + $b

expr $a - $b

expr $a * $b

expr $a / $b

expr $a % b a = b a= ba=b

複制代碼

注意: 1. 在expr中的乖号為:*

  1. 在 expr中的 表達式與運算符之間要有空格,否則錯誤;
  2. 在[ $a == $b ]與[ $a != $b ]中,要需要在方括号與變量以及變量與運算符之間也需要有括号, 否則為錯誤的。(親測過)

關系運算符:

隻支援數字,不支援字元串,除非字元串的值是數字。常見的有:

image

注意:也别忘記了空格;

布爾運算符:

image

字元串運算符:

image

檔案測試運算符:

檢測 Unix 檔案的各種屬性。

image

Shell中的字元串

單引号的限制:

單引号裡的任何字元都會原樣輸出,單引号字元串中的變量是無效的;

單引号字串中不能出現單引号(對單引号使用轉義符後也不行)。

雙引号的優點:

雙引号裡可以有變量

雙引号裡可以出現轉義字元

拼接字元串:

country=“China”

echo “hello, KaTeX parse error: Expected 'EOF', got '#' at position 10: country" #̲也可以 echo "hello…country” "

擷取字元串長度:

string=“abcd”

echo ${#string} #輸出 4

提取子字元串:

string=“alibaba is a great company”

echo ${string:1:4} #輸出liba

查找子字元串:

string=“alibaba is a great company”

echo

expr index "$string" is

處理路經的字元串:

例如:當一個路徑為 /home/xiaoming/1.txt時,如何怎麼它的路徑(不帶檔案) 和如何得到它的檔案名??

得到檔案名使用 bashname指令:

複制代碼

參數:

-a,表示處理多個路徑;

-s, 用于去掉指定的檔案的字尾名;

basename /home/yin/1.txt -> 1.txt

basename -a /home/yin/1.txt /home/zhai/2.sh ->

1.txt

2.sh basename -s .txt /home/yin/1.txt -> 1

basename /home/yin/1.txt .txt -> 1

複制代碼

得到路徑名(不帶檔案名)使用 dirname指令:

複制代碼

參數:沒有啥參數;

//例子:

dirname /usr/bin/ -> /usr

dirname dir1/str dir2/str ->

dir1

dir2

dirname stdio.h -> .

複制代碼

Shell的數組:

bash支援一維數組, 不支援多元數組, 它的下标從0開始編号. 用下标[n] 擷取數組元素;

定義數組:

在shell中用括号表示數組,元素用空格分開。 如:

array_name=(value0 value1 value2 value3)

也可以單獨定義數組的各個分量,可以不使用連續的下标,而且下标的範圍沒有限制。如:

array_name[0]=value0

array_name[1]=value1

array_name[2]=value2

讀取數組:

讀取某個下标的元素一般格式為:

${array_name[index]}

讀取數組的全部元素,用@或*

${array_name[*]}

${array_name[@]}

擷取數組的資訊:

取得數組元素的個數:

length=KaTeX parse error: Expected '}', got '#' at position 2: {#̲array_name[@]} …{#array_name[*]}

擷取數組的下标:

length=KaTeX parse error: Expected 'EOF', got '#' at position 18: …array_name[@]} #̲或 length={!array_name[*]}

取得數組單個元素的長度:

lengthn=${#array_name[n]}

printf函數:

它與c語言中的printf相似,不過也有不同,下面列出它的不同的地方:

printf 指令不用加括号

format-string 可以沒有引号,但最好加上,單引号雙引号均可。

參數多于格式控制符(%)時,format-string 可以重用,可以将所有參數都轉換。

arguments 使用空格分隔,不用逗号。

下面為例子:

複制代碼

format-string為雙引号

$ printf “%d %s\n” 1 “abc”

1 abc

單引号與雙引号效果一樣

$ printf ‘%d %s\n’ 1 “abc”

1 abc

沒有引号也可以輸出

$ printf %s abcdef

abcdef

格式隻指定了一個參數,但多出的參數仍然會按照該格式輸出,format-string 被重用

$ printf %s abc def

abcdef

$ printf “%s\n” abc def

abc

def

$ printf “%s %s %s\n” a b c d e f g h i j

a b c

d e f

g h i

j

如果沒有 arguments,那麼 %s 用NULL代替,%d 用 0 代替

$ printf “%s and %d \n”

and 0

如果以 %d 的格式來顯示字元串,那麼會有警告,提示無效的數字,此時預設置為 0

$ printf “The first program always prints’%s,%d\n’” Hello Shell

-bash: printf: Shell: invalid number

The first program always prints ‘Hello,0’

$

複制代碼

Shell中條件語句

if 語句

包括:1, if [ 表達式 ] then 語句 fi

  1. if [ 表達式 ] then 語句 else 語句 fi
  2. if [ 表達式] then 語句 elif[ 表達式 ] then 語句 elif[ 表達式 ] then 語句 …… fi

例子:

複制代碼

a=10

b=20

if [ $a == $b ]

then

echo “a is equal to b”

else

echo “a is not equal to b”

fi

複制代碼

另外:if … else 語句也可以寫成一行,以指令的方式來運作,像這樣:

if test $[2*3] -eq $[1+5]; then echo ‘The two numbers are equal!’; fi;

其中,test 指令用于檢查某個條件是否成立,與方括号([ ])類似。

case …… esac語句

case … esac 與其他語言中的 switch … case 語句類似,是一種多分枝選擇結構。case語句格式如下:

複制代碼

case 值 in

模式1)

command1

command2

command3

;;

模式2)

command1

command2

command3

;;

*)

command1

command2

command3

;;

esac

複制代碼

其中, 1. 取值後面必須為關鍵字 in,每一模式必須以右括号結束。取值可以為變量或常數。比對發現取值符合某一模式後,其間所有指令開始執行直至 ;;。;; 與其他語言中的 break 類似,意思是跳到整個 case 語句的最後。2. 如果無一比對模式,使用星号 * 捕獲該值,再執行後面的指令。

Shell 的循環語句

for 循環

一般格式為:

複制代碼

for 變量 in 清單

do

command1

command2

commandN

done

複制代碼

注意:清單是一組值(數字、字元串等)組成的序列,每個值通過空格分隔。每循環一次,就将清單中的下一個值賦給變量。 例如:

順序輸出目前清單的數字:

for loop in 1 2 3 4 5

do

echo “The value is: $loop”

done

顯示主目錄下以 .bash 開頭的檔案:

#!/bin/bash

for FILE in $HOME/.bash*

do

echo $FILE

done

while循環

一般格式為:

while command

do

Statement(s) to be executed if command is true

done

例如:

COUNTER=0

while [ $COUNTER -lt 5 ]

do

COUNTER=‘expr $COUNTER+1’

echo $COUNTER

done

until 循環

until 循環執行一系列指令直至條件為 true 時停止。until 循環與 while 循環在處理方式上剛好相反。 常用格式為:

until command

do

Statement(s) to be executed until command is true

done

command 一般為條件表達式,如果傳回值為 false,則繼續執行循環體内的語句,否則跳出循環。

類似地, 在循環中使用 break 與continue 跳出循環。 另外,break 指令後面還可以跟一個整數,表示跳出第幾層循環。

Shell函數

Shell函數必須先定義後使用,定義如下,

function_name () {

list of commands

[ return value ]

}

也可以加上function關鍵字:

function function_name () {

list of commands

[ return value ]

}

注意:1. 調用函數隻需要給出函數名,不需要加括号。

  1. 函數傳回值,可以顯式增加return語句;如果不加,會将最後一條指令運作結果作為傳回值。
  2. Shell 函數傳回值隻能是整數,一般用來表示函數執行成功與否,0表示成功,其他值表示失敗。
  3. 函數的參數可以通過 $n 得到.如:

複制代碼

funWithParam(){

echo “The value of the first parameter is $1 !”

echo “The value of the second parameter is $2 !”

echo “The value of the tenth parameter is ${10} !”

echo “The value of the eleventh parameter is ${11} !”

echo “The amount of the parameters is $# !” # 參數個數

echo “The string of the parameters is $* !” # 傳遞給函數的所有參數

}

funWithParam 1 2 3 4 5 6 7 8 9 34 73

複制代碼

5. 像删除變量一樣,删除函數也可以使用 unset 指令,不過要加上 .f 選項,如下所示:

unset .f function_name

shell的檔案包含:

Shell 也可以包含外部腳本,将外部腳本的内容合并到目前腳本。使用:

. filename

#或

source filename

  1. 兩種方式的效果相同,簡單起見,一般使用點号(.),但是注意點号(.)和檔案名中間有一空格。
  2. 被包含腳本不需要有執行權限。

繼續閱讀