學一下shell編程

Shell變量

(1)定義變量的時候,賦值號=周圍不能有空格

(2)定義變量時不需要$符號,而使用變量時可以用$var或這${var},推薦使用${}的方式,便於解釋器識別變量邊界。

name="Lethe"
echo ${name}

(3)單引號與雙引號的區別

  • 單引號''包圍變量的值時,單引號裏面是什麼就輸出什麼,即使內容中有變量和命令(命令需要反引起來)也會把它們原樣輸出。
  • 雙引號""包圍變量的值時,輸出時會先解析裏面的變量和命令。

(4)將命令的執行結果賦給一個變量有下面兩種方式:

  • 反引號
    在這裏插入圖片描述
  • $() (推薦使用)
    在這裏插入圖片描述
    (5)計算表達式:$(())
    在這裏插入圖片描述
    (6)通過readonly可以將變量聲明爲只讀變量,只讀變量不能被改變,也不能被unset命令刪除。
    在這裏插入圖片描述

Shell特殊變量

(1)特殊變量列表

變量 含義
$0 當前腳本的文件名
$n 傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。
$# 傳遞給腳本或函數的參數個數。
$* 傳遞給腳本或函數的所有參數。
$@ 傳遞給腳本或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同。
$? 上個命令的退出狀態,或函數的返回值。
$$ 當前Shell進程ID。對於 Shell 腳本,就是這些腳本所在的進程ID。
#!/bin/bash
echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"

在這裏插入圖片描述

(2)$*$@的區別
$*$@ 都表示傳遞給函數或腳本的所有參數,不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數。

但是當它們被雙引號(" ")包含時:

  • "$*" 會將所有的參數作爲一個整體,以"$1 $2 … $n"的形式輸出所有參數;
  • "$@" 會將各個參數分開,以"$1" "$2" … "$n"的形式輸出所有參數。

Shell替換

(1)如果表達式中包含特殊字符,Shell 將會進行替換。例如,在雙引號中使用變量就是一種替換,轉義字符也是一種替換。
在這裏插入圖片描述
這裏 -e 表示對轉義字符進行替換。如果不使用 -e 選項,將會原樣輸出。

下面的轉義字符都可以用在 echo 中:

轉義字符 含義
\\ 反斜槓
\a 警報,響鈴
\b 退格(刪除鍵)
\f 換頁(FF),將當前位置移到下頁開頭
\n 換行
\r 回車
\t 水平製表符(tab鍵)
\v 垂直製表符

也可以使用 echo 命令的 -E 選項禁止轉義,默認也是不轉義的;使用 -n 選項可以禁止插入換行符。

(2)命令替換

命令替換是指Shell可以先執行命令,將輸出結果暫時保存,在適當的地方輸出。
在這裏插入圖片描述

(3)變量替換

變量替換可以根據變量的狀態(是否爲空、是否定義等)來改變它的值。

可以使用的變量替換形式:

形式 說明
${var} 變量本來的值
${var:-word} 如果變量 var 爲空或已被刪除(unset),那麼返回 word,但不改變 var 的值。
${var:=word} 如果變量 var 爲空或已被刪除(unset),那麼返回 word,並將 var 的值設置爲 word。
${var:?message} 如果變量 var 爲空或已被刪除(unset),那麼將消息 message 送到標準錯誤輸出,可以用來檢測量 var 是否可以被正常賦值。若此替換出現在Shell腳本中,那麼腳本將停止運行。
${var:+word} 如果變量 var 被定義,那麼返回 word,但不改變 var 的值。
#!/bin/bash

echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}"

echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}"

unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var"

var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var"

echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"

在這裏插入圖片描述


Shell運算符

(1)原生bash不支持簡單的數學運算,但是可以通過其他命令來實現,例如 awk 和 expr,expr 最常用。
在這裏插入圖片描述

  • 表達式和運算符之間要有空格,例如 2+2 是不對的,必須寫成 2 + 2
  • 完整的表達式要被反引號包含

(2)算數運算符

運算符 說明 舉例
+ 加法 `expr $a + $b` 結果爲 30。
- 減法 `expr $a - $b` 結果爲 10。
* 乘法 `expr $a * $b` 結果爲 200。
/ 除法 `expr $b / $a` 結果爲 2。
% 取餘 `expr $b % $a` 結果爲 0。
= 賦值 a=$b 將把變量 b 的值賦給 a。
== 相等。用於比較兩個數字,相同則返回 true。 [ $a == $b ] 返回 false。
!= 不相等。用於比較兩個數字,不相同則返回 true。 [ $a != $b ] 返回 true。
  • 乘號(*)前邊必須加反斜槓()才能實現乘法運算;
  • 條件表達式要放在方括號之間,並且要有空格,例如 [$a==$b] 是錯誤的,必須寫成 [ $a == $b ]

(3)關係運算符
關係運算符只支持數字,不支持字符串,除非字符串的值是數字。

運算符 說明 舉例
-eq 檢測兩個數是否相等,相等返回 true,相當於== [ $a -eq $b ] 返回 true。
-ne 檢測兩個數是否相等,不相等返回 true,相當於!= [ $a -ne $b ] 返回 true。
-gt 檢測左邊的數是否大於右邊的,如果是,則返回 true,相當於> [ $a -gt $b ] 返回 false。
-lt 檢測左邊的數是否小於右邊的,如果是,則返回 true,相當於< [ $a -lt $b ] 返回 true。
-ge 檢測左邊的數是否大等於右邊的,如果是,則返回 true,相當於>= [ $a -ge $b ] 返回 false。
-le 檢測左邊的數是否小於等於右邊的,如果是,則返回 true,相當於<= [ $a -le $b ] 返回 true。

(4)布爾運算符

運算符 說明 舉例
! 非運算,表達式爲 true 則返回 false,否則返回 true。 [ ! false ] 返回 true。
-o 或運算,有一個表達式爲 true 則返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 與運算,兩個表達式都爲 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

(5)字符串運算符

運算符 說明 舉例
= 檢測兩個字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 檢測兩個字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 檢測字符串長度是否爲0,爲0返回 true。 [ -z $a ] 返回 false。
-n 檢測字符串長度是否爲0,不爲0返回 true。 [ -z $a ] 返回 true。
str 檢測字符串是否爲空,不爲空返回 true。 [ $a ] 返回 true。

Shell註釋

  • 以“#”開頭的行就是註釋,會被解釋器忽略。

  • sh裏沒有多行註釋,只能每一行加一個#號

Shell字符串

(1)拼接字符串

string1="Hello"
string2="World"
echo $string1 $string2 # 輸出Hello World

(2)獲取字符串長度

string="abcd"
echo ${#string} #輸出 4

(3)提取子字符串

string="Hello Word"
echo ${string:1:4} #輸出ello

(4)查找子字符串

string="Hello World"
echo `expr index "$string" lo` # 輸出3

Shell數組

(1)定義數組
在Shell中,用括號來表示數組,數組元素用“空格”符號分割開

array_name=(value0 value1 value2 value3)

或單獨定義數組的各個分量:

array_name[0]=value0
array_name[1]=value1
array_name[2]=value2

可以不使用連續的下標,而且下標的範圍沒有限制。

(2)讀取數組

讀取數組格式:${array_name[index]}

valuen=${array_name[2]}
  • 使用@*可以獲取數組中的所有元素。
${array_name[*]}
${array_name[@]}
  • 獲取數組長度的方法與獲取字符串長度的方法相同
# 取得數組元素的個數
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得數組單個元素的長度
lengthn=${#array_name[n]}

if else語句

(1)if … else 語句

if [ expression ]
then
   Statement(s) to be executed if expression is true
fi
  • 如果 expression 返回 true,then 後邊的語句將會被執行;如果返回 false,不會執行任何語句。
  • 最後必須以 fi 來結尾閉合 if。
  • expression 和方括號([ ])之間必須有空格,否則會有語法錯誤。

(2)if … else … fi 語句

if [ expression ]
then
   Statement(s) to be executed if expression is true
else
   Statement(s) to be executed if expression is not true
fi

如果 expression 返回 true,那麼 then 後邊的語句將會被執行;否則,執行 else 後邊的語句。

(3)if … elif … fi 語句

if [ expression 1 ]
then
   Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
   Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
   Statement(s) to be executed if expression 3 is true
else
   Statement(s) to be executed if no expression is true
fi

哪一個 expression 的值爲 true,就執行哪個 expression 後面的語句;如果都爲 false,那麼不執行任何語句。

(4)if … else 語句也可以寫成一行,以命令的方式來運行,像這樣:

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

test 命令用於檢查某個條件是否成立,與方括號([ ])類似。


case esac語句

case 語句匹配一個值或一個模式,如果匹配成功,執行相匹配的命令,與其他語言的switch … case類似。

case語句格式如下:

casein
模式1)
    command1
    command2
    command3
    ;;
模式2)
    command1
    command2
    command3
    ;;
*)
    command1
    command2
    command3
    ;;
esac

例子:

#!/bin/bash
option="${1}"
case ${option} in
   -f) FILE="${2}"
      echo "File name is $FILE"
      ;;
   -d) DIR="${2}"
      echo "Dir name is $DIR"
      ;;
   *) 
      echo "`basename ${0}`:usage: [-f file] | [-d directory]"
      exit 1 # Command to come out of the program with status 1
      ;;
esac

運行結果:

$./test.sh
test.sh: usage: [ -f filename ] | [ -d directory ]
$ ./test.sh -f index.htm
$ vi test.sh
$ ./test.sh -f index.htm
File name is index.htm
$ ./test.sh -d unix
Dir name is unix
$

for循環

格式如下:

for 變量 in 列表
do
    command1
    command2
    ...
    commandN
done
  • 列表是一組值(數字、字符串等)組成的序列,每個值通過空格分隔。每循環一次,就將列表中的下一個值賦給變量。

  • in 列表是可選的,如果不用它,for 循環使用命令行的位置參數。

#!/bin/bash
for loop in 1 2 3 4 5
do
	echo "The value is: $loop"
done

在這裏插入圖片描述


while循環

while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令通常爲測試條件。其格式爲:

while command
do
   Statement(s) to be executed if command is true
done

例子:

#!/bin/bash
count=0
while [ $count -lt 5]
do
	count=`expr $count + 1`
	echo $count
done

在這裏插入圖片描述


until循環

until 循環執行一系列命令直至條件爲 true 時停止。until 循環與 while 循環在處理方式上剛好相反。

until command
do
   Statement(s) to be executed until command is true
done

break和continue命令

(1)break

  • break命令允許跳出所有循環(終止執行後面的所有循環)。
  • 在嵌套循環中,break 命令後面還可以跟一個整數,表示跳出第幾層循環。例如:
break n

表示跳出第 n 層循環。

(2)continue

  • continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環。
  • continue 後面也可以跟一個數字,表示跳出第幾層循環。

Shell函數

Shell函數的定義格式如下:

function_name() {
	list of commands
	[ return value ]
}

Shell 函數返回值只能是整數,一般用來表示函數執行成功與否,0表示成功,其他值表示失敗。

如果 return 其他數據,比如一個字符串,往往會得到錯誤提示:“numeric argument required”。

如果一定要讓函數返回字符串,那麼可以先定義一個變量,用來接收函數的計算結果,腳本在需要的時候訪問這個變量來獲得函數返回值。

例子:

#!/bin/bash
funWithReturn(){
    echo "The function is to get the sum of two numbers..."
    echo -n "Input first number: "
    read aNum
    echo -n "Input another number: "
    read anotherNum
    echo "The two numbers are $aNum and $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
# Capture value returnd by last command
ret=$?
echo "The sum of two numbers is $ret !"

在這裏插入圖片描述

在函數內部可以用 $n 的形式來獲取參數的值,例如,$1表示第一個參數,$2表示第二個參數…

特殊變量 說明
$# 傳遞給函數的參數個數。
$* 顯示所有傳遞給函數的參數。
$@ 與$*相同,但是略有區別,請查看Shell特殊變量。
$? 函數的返回值。

輸入輸出重定向

一般情況下,每個 Unix/Linux 命令運行時都會打開三個文件:

  • 標準輸入文件(stdin):stdin的文件描述符爲0,Unix程序默認從stdin讀取數據。
  • 標準輸出文件(stdout):stdout 的文件描述符爲1,Unix程序默認向stdout輸出數據。
  • 標準錯誤文件(stderr):stderr的文件描述符爲2,Unix程序會向stderr流中寫入錯誤信息
命令 說明
command > file 將輸出重定向到 file。
command < file 將輸入重定向到 file。
command >> file 將輸出以追加的方式重定向到 file。
n > file 將文件描述符爲 n 的文件重定向到 file。
n >> file 將文件描述符爲 n 的文件以追加的方式重定向到 file。
n >& m 將輸出文件 m 和 n 合併。
n <& m 將輸入文件 m 和 n 合併。
<< tag 將開始標記 tag 和結束標記 tag 之間的內容作爲輸入。

Shell文件包含

Shell 中包含腳本可以使用:

. filename

source filename

通常使用點號.,注意點號.和文件名中間有一空格。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章