一、 Shell簡介:什麼是Shell,Shell命令的兩種執行方式1html
4、何時使用Shell3github
6、Shell變量:Shell變量的定義、刪除變量、只讀變量、變量類型5shell
7、Shell特殊變量:Shell $0, $#, $*, $@, $?, $$和命令行參數6express
八、 Shell替換:Shell變量替換,命令替換,轉義字符9編程
九、 Shell運算符:Shell算數運算符、關係運算符、布爾運算符、字符串運算符12數組
十、 Shell註釋20xcode
二11、Shell函數:Shell函數返回值、刪除函數、在終端調用函數35
二十3、Shell輸入輸出重定向:Shell Here Document,/dev/null文件38
9、Shell運算符:Shell算數運算符、關係運算符、布爾運算符、字符串運算符
Bash 支持不少運算符,包括算數運算符、關係運算符、布爾運算符、字符串運算符和文件測試運算符。
原生bash不支持簡單的數學運算,可是能夠經過其餘命令來實現,例如 awk 和 expr,expr 最經常使用。
expr 是一款表達式計算工具,使用它能完成表達式的求值操做。
例如,兩個數相加:
#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"
運行腳本輸出:
Total value : 4
注意:
1、表達式和運算符之間要有空格,例如 2+2 是不對的,必須寫成 2 + 2,這與咱們熟悉的大多數編程語言不同。
2、完整的表達式要被 ` ` 包含,注意這個字符不是經常使用的單引號,在 Esc 鍵下邊。
算術運算符
先來看一個使用算術運算符的例子:
#!/bin/sh
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
echo "a is equal to b"
fi
if [ $a != $b ]
then
echo "a is not equal to b"
fi
運行結果:
a + b : 30a - b : -10a * b : 200b / a : 2b % a : 0a is not equal to b
注意:
乘號(*)前邊必須加反斜槓(\)才能實現乘法運算;
if...then...fi 是條件語句,後續將會講解。
算術運算符列表 |
||
運算符 |
說明 |
舉例 |
+ |
加法 |
`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 ]。
關係運算符
關係運算符只支持數字,不支持字符串,除非字符串的值是數字。
先來看一個關係運算符的例子:
#!/bin/sh
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a is equal to b"
else
echo "$a -eq $b: a is not equal to b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a is not equal to b"
else
echo "$a -ne $b : a is equal to b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a is greater than b"
else
echo "$a -gt $b: a is not greater than b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a is less than b"
else
echo "$a -lt $b: a is not less than b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a is greater or equal to b"
else
echo "$a -ge $b: a is not greater or equal to b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a is less or equal to b"
else
echo "$a -le $b: a is not less or equal to b"
fi
運行結果:
10 -eq 20: a is not equal to b10 -ne 20: a is not equal to b10 -gt 20: a is not greater than b10 -lt 20: a is less than b10 -ge 20: a is not greater or equal to b10 -le 20: a is less or equal to b
關係運算符列表 |
||
運算符 |
說明 |
舉例 |
-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。 |
布爾運算符
先來看一個布爾運算符的例子:
#!/bin/sh
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a is not equal to b"
else
echo "$a != $b: a is equal to b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a -lt 100 -a $b -gt 15 : returns true"
else
echo "$a -lt 100 -a $b -gt 15 : returns false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a -lt 100 -o $b -gt 100 : returns true"
else
echo "$a -lt 100 -o $b -gt 100 : returns false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a -lt 100 -o $b -gt 100 : returns true"
else
echo "$a -lt 100 -o $b -gt 100 : returns false"
fi
運行結果:
10 != 20 : a is not equal to b10 -lt 100 -a 20 -gt 15 : returns true10 -lt 100 -o 20 -gt 100 : returns true10 -lt 5 -o 20 -gt 100 : returns false
布爾運算符列表 |
||
運算符 |
說明 |
舉例 |
! |
非運算,表達式爲 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。 |
字符串運算符
先來看一個例子:
#!/bin/sh
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a is equal to b"
else
echo "$a = $b: a is not equal to b"
fi
if [ $a != $b ]
then
echo "$a != $b : a is not equal to b"
else
echo "$a != $b: a is equal to b"
fi
if [ -z $a ]
then
echo "-z $a : string length is zero"
else
echo "-z $a : string length is not zero"
fi
if [ -n $a ]
then
echo "-n $a : string length is not zero"
else
echo "-n $a : string length is zero"
fi
if [ $a ]
then
echo "$a : string is not empty"
else
echo "$a : string is empty"
fi
運行結果:
abc = efg: a is not equal to babc != efg : a is not equal to b-z abc : string length is not zero-n abc : string length is not zeroabc : string is not empty
字符串運算符列表 |
||
運算符 |
說明 |
舉例 |
= |
檢測兩個字符串是否相等,相等返回 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。 |
文件測試運算符
文件測試運算符用於檢測 Unix 文件的各類屬性。
例如,變量 file 表示文件「/var/www/tutorialspoint/unix/test.sh」,它的大小爲100字節,具備 rwx 權限。下面的代碼,將檢測該文件的各類屬性:
#!/bin/sh
file="/var/www/tutorialspoint/unix/test.sh"
if [ -r $file ]
then
echo "File has read access"
else
echo "File does not have read access"
fi
if [ -w $file ]
then
echo "File has write permission"
else
echo "File does not have write permission"
fi
if [ -x $file ]
then
echo "File has execute permission"
else
echo "File does not have execute permission"
fi
if [ -f $file ]
then
echo "File is an ordinary file"
else
echo "This is sepcial file"
fi
if [ -d $file ]
then
echo "File is a directory"
else
echo "This is not a directory"
fi
if [ -s $file ]
then
echo "File size is zero"
else
echo "File size is not zero"
fi
if [ -e $file ]
then
echo "File exists"
else
echo "File does not exist"
fi
運行結果:
File has read accessFile has write permissionFile has execute permissionFile is an ordinary fileThis is not a directoryFile size is zeroFile exists
文件測試運算符列表 |
||
操做符 |
說明 |
舉例 |
-b file |
檢測文件是不是塊設備文件,若是是,則返回 true。 |
[ -b $file ] 返回 false。 |
-c file |
檢測文件是不是字符設備文件,若是是,則返回 true。 |
[ -b $file ] 返回 false。 |
-d file |
檢測文件是不是目錄,若是是,則返回 true。 |
[ -d $file ] 返回 false。 |
-f file |
檢測文件是不是普通文件(既不是目錄,也不是設備文件),若是是,則返回 true。 |
[ -f $file ] 返回 true。 |
-g file |
檢測文件是否設置了 SGID 位,若是是,則返回 true。 |
[ -g $file ] 返回 false。 |
-k file |
檢測文件是否設置了粘着位(Sticky Bit),若是是,則返回 true。 |
[ -k $file ] 返回 false。 |
-p file |
檢測文件是不是具名管道,若是是,則返回 true。 |
[ -p $file ] 返回 false。 |
-u file |
檢測文件是否設置了 SUID 位,若是是,則返回 true。 |
[ -u $file ] 返回 false。 |
-r file |
檢測文件是否可讀,若是是,則返回 true。 |
[ -r $file ] 返回 true。 |
-w file |
檢測文件是否可寫,若是是,則返回 true。 |
[ -w $file ] 返回 true。 |
-x file |
檢測文件是否可執行,若是是,則返回 true。 |
[ -x $file ] 返回 true。 |
-s file |
檢測文件是否爲空(文件大小是否大於0),不爲空返回 true。 |
[ -s $file ] 返回 true。 |
-e file |
檢測文件(包括目錄)是否存在,若是是,則返回 true。 |
[ -e $file ] 返回 true。 |
以「#」開頭的行就是註釋,會被解釋器忽略。
sh裏沒有多行註釋,只能每一行加一個#號。只能像這樣:
#--------------------------------------------
# 這是一個自動打ipa的腳本,基於webfrogs的ipa-build書寫:
# https://github.com/webfrogs/xcode_shell/blob/master/ipa-build
# 功能:自動爲etao ios app打包,產出物爲14個渠道的ipa包
# 特點:全自動打包,不須要輸入任何參數
#--------------------------------------------
##### 用戶配置區 開始 #####
#
#
# 項目根目錄,推薦將此腳本放在項目的根目錄,這裏就不用改了
# 應用名,確保和Xcode裏Product下的target_name.app名字一致
#
##### 用戶配置區 結束 #####
若是在開發過程當中,遇到大段的代碼須要臨時註釋起來,過一下子又取消註釋,怎麼辦呢?每一行加個#符號太費力了,能夠把這一段要註釋的代碼用一對花括號括起來,定義成一個函數,沒有地方調用這個函數,這塊代碼就不會執行,達到了和註釋同樣的效果。
字符串是shell編程中最經常使用最有用的數據類型(除了數字和字符串,也沒啥其它類型好用了),字符串能夠用單引號,也能夠用雙引號,也能夠不用引號。單雙引號的區別跟PHP相似。
單引號
str='this is a string'
單引號字符串的限制:
單引號裏的任何字符都會原樣輸出,單引號字符串中的變量是無效的;
單引號字串中不能出現單引號(對單引號使用轉義符後也不行)。
雙引號
your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"
雙引號的優勢:
雙引號裏能夠有變量
雙引號裏能夠出現轉義字符
拼接字符串
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
獲取字符串長度
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`
Shell在編程方面比Windows批處理強大不少,不管是在循環、運算。
bash支持一維數組(不支持多維數組),而且沒有限定數組的大小。相似與C語言,數組元素的下標由0開始編號。獲取數組中的元素要利用下標,下標能夠是整數或算術表達式,其值應大於或等於0。
定義數組
在Shell中,用括號來表示數組,數組元素用「空格」符號分割開。定義數組的通常形式爲:
array_name=(value1 ... valuen)
例如:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
還能夠單獨定義數組的各個份量:
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
能夠不使用連續的下標,並且下標的範圍沒有限制。
讀取數組
讀取數組元素值的通常格式是:
${array_name[index]}
例如:
valuen=${array_name[2]}
舉個例子:
#!/bin/sh
NAME[0]="Zara"
NAME[1]="Qadir"
NAME[2]="Mahnaz"
NAME[3]="Ayan"
NAME[4]="Daisy"
echo "First Index: ${NAME[0]}"
echo "Second Index: ${NAME[1]}"
運行腳本,輸出:
$./test.shFirst Index: ZaraSecond Index: Qadir
使用@ 或 * 能夠獲取數組中的全部元素,例如:
${array_name[*]}
${array_name[@]}
舉個例子:
#!/bin/sh
NAME[0]="Zara"
NAME[1]="Qadir"
NAME[2]="Mahnaz"
NAME[3]="Ayan"
NAME[4]="Daisy"
echo "First Method: ${NAME[*]}"
echo "Second Method: ${NAME[@]}"
運行腳本,輸出:
$./test.shFirst Method: Zara Qadir Mahnaz Ayan DaisySecond Method: Zara Qadir Mahnaz Ayan Daisy
獲取數組的長度
獲取數組長度的方法與獲取字符串長度的方法相同,例如:
# 取得數組元素的個數
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得數組單個元素的長度
lengthn=${#array_name[n]}
echo是Shell的一個內部指令,用於在屏幕上打印出指定的字符串。命令格式:
echo arg
您可使用echo實現更復雜的輸出格式控制。
顯示轉義字符
echo "\"It is a test\""
結果將是:
"It is a test"
雙引號也能夠省略。
顯示變量
name="OK"
echo "$name It is a test"
結果將是:
OK It is a test
一樣雙引號也能夠省略。
若是變量與其它字符相連的話,須要使用大括號({ }):
mouth=8
echo "${mouth}-1-2009"
結果將是:
8-1-2009
顯示換行
echo "OK!\n"
echo "It is a test"
輸出:
OK!
It is a test
顯示不換行
echo "OK!\c"
echo "It is a test"
輸出:
OK!It si a test
顯示結果重定向至文件
echo "It is a test" > myfile
原樣輸出字符串
若須要原樣輸出字符串(不進行轉義),請使用單引號。例如:
echo '$name\"'
顯示命令執行結果
echo `date`
結果將顯示當前日期
從上面可看出,雙引號無關緊要,單引號主要用在原樣輸出中。
printf 命令用於格式化輸出, 是echo命令的加強版。它是C語言printf()庫函數的一個有限的變形,而且在語法上有些不一樣。
注意:printf 由 POSIX 標準所定義,移植性要比 echo 好。
如同 echo 命令,printf 命令也能夠輸出簡單的字符串:
$printf "Hello, Shell\n"
Hello, Shell
$
printf 不像 echo 那樣會自動換行,必須顯式添加換行符(\n)。
printf 命令的語法:
printf format-string [arguments...]
format-string 爲格式控制字符串,arguments 爲參數列表。
printf()在C語言入門教程中已經講到,功能和用法與 printf 命令相似,請查看:C語言格式輸出函數printf()詳解
這裏僅說明與C語言printf()函數的不一樣:
1、printf 命令不用加括號
2、format-string 能夠沒有引號,但最好加上,單引號雙引號都可。
3、參數多於格式控制符(%)時,format-string 能夠重用,能夠將全部參數都轉換。
4、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'
$
注意:根據POSIX標準,浮點格式%e、%E、%f、%g與%G是「不須要被支持」。這是由於awk支持浮點預算,且有它本身的printf語句。這樣Shell程序中須要將浮點數值進行格式化的打印時,可以使用小型的awk程序實現。然而,內建於bash、ksh93和zsh中的printf命令都支持浮點格式。
if 語句經過關係運算符判斷表達式的真假來決定執行哪一個分支。Shell 有三種 if ... else 語句:
A、if ... fi 語句;
B、if ... else ... fi 語句;
C、if ... elif ... else ... fi 語句。
1) if ... else 語句
if ... else 語句的語法:
if [ expression ]then Statement(s) to be executed if expression is truefi
若是 expression 返回 true,then 後邊的語句將會被執行;若是返回 false,不會執行任何語句。
最後必須以 fi 來結尾閉合 if,fi 就是 if 倒過來拼寫,後面也會碰見。
注意:expression 和方括號([ ])之間必須有空格,不然會有語法錯誤。
舉個例子:
#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
echo "a is equal to b"
fi
if [ $a != $b ]
then
echo "a is not equal to b"
fi
運行結果:
a is not equal to b
2) if ... else ... fi 語句
if ... else ... fi 語句的語法:
if [ expression ]then Statement(s) to be executed if expression is trueelse Statement(s) to be executed if expression is not truefi
若是 expression 返回 true,那麼 then 後邊的語句將會被執行;不然,執行 else 後邊的語句。
舉個例子:
#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
echo "a is equal to b"
else
echo "a is not equal to b"
fi
執行結果:
a is not equal to b
3) if ... elif ... fi 語句
if ... elif ... fi 語句能夠對多個條件進行判斷,語法爲:
if [ expression 1 ]then Statement(s) to be executed if expression 1 is trueelif [ expression 2 ]then Statement(s) to be executed if expression 2 is trueelif [ expression 3 ]then Statement(s) to be executed if expression 3 is trueelse Statement(s) to be executed if no expression is truefi
哪個 expression 的值爲 true,就執行哪一個 expression 後面的語句;若是都爲 false,那麼不執行任何語句。
舉個例子:
#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
echo "a is equal to b"
elif [ $a -gt $b ]
then
echo "a is greater than b"
elif [ $a -lt $b ]
then
echo "a is less than b"
else
echo "None of the condition met"
fi
運行結果:
a is less than b
if ... else 語句也能夠寫成一行,以命令的方式來運行,像這樣:
if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;
if ... else 語句也常常與 test 命令結合使用,以下所示:
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo 'The two numbers are equal!'
else
echo 'The two numbers are not equal!'
fi
輸出:
The two numbers are equal!
test 命令用於檢查某個條件是否成立,與方括號([ ])相似。
case ... esac 與其餘語言中的 switch ... case 語句相似,是一種多分枝選擇結構。
case 語句匹配一個值或一個模式,若是匹配成功,執行相匹配的命令。case語句格式以下:
case 值 in模式1) command1 command2 command3 ;;模式2) command1 command2 command3 ;;*) command1 command2 command3 ;;esac
case工做方式如上所示。取值後面必須爲關鍵字 in,每一模式必須以右括號結束。取值能夠爲變量或常數。匹配發現取值符合某一模式後,其間全部命令開始執行直至 ;;。;; 與其餘語言中的 break 相似,意思是跳到整個 case 語句的最後。
取值將檢測匹配的每個模式。一旦模式匹配,則執行完匹配模式相應命令後再也不繼續其餘模式。若是無一匹配模式,使用星號 * 捕獲該值,再執行後面的命令。
下面的腳本提示輸入1到4,與每一種模式進行匹配:
echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
1) echo 'You select 1'
;;
2) echo 'You select 2'
;;
3) echo 'You select 3'
;;
4) echo 'You select 4'
;;
*) echo 'You do not select a number between 1 to 4'
;;
esac
輸入不一樣的內容,會有不一樣的結果,例如:
Input a number between 1 to 4Your number is:3You select 3
再舉一個例子:
#!/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.shtest.sh: usage: [ -f filename ] | [ -d directory ]$ ./test.sh -f index.htm$ vi test.sh$ ./test.sh -f index.htmFile name is index.htm$ ./test.sh -d unixDir name is unix$
aNum in
1|2|3|4|5) echo "Your number is $aNum!"
;;
*) echo "You do not select a number between 1 to 5!"
continue
echo "Game is over!"
;;
esac
done
運行代碼發現,當輸入大於5的數字時,該例中的循環不會結束,語句
echo "Game is over!"
永遠不會被執行。
一樣,continue 後面也能夠跟一個數字,表示跳出第幾層循環。
再看一個 continue 的例子:
#!/bin/bash
NUMS="1 2 3 4 5 6 7"
for NUM in $NUMS
do
Q=`expr $NUM % 2`
if [ $Q -eq 0 ]
then
echo "Number is an even number!!"
continue
fi
echo "Found odd number"
done
運行結果:
Found odd numberNumber is an even number!!Found odd numberNumber is an even number!!Found odd numberNumber is an even number!!Found odd number
因爲篇幅問題,後面內容在Linux-shell-徹底詳解(3)