建立 helloWorld.sh
文件,寫入以下內容:shell
#!/bin/bash echo "hello world"
其中 #!
告訴系統其後路徑所指定的程序是解釋此腳本文件的 Shell 程序,常見的 Shell 程序有如下幾類(可經過命令 cat /etc/shells
查看):apache
其中 Bash 在平常工做中被普遍使用,同時也是大多數 Linux 系統默認的 Shell。數組
執行該 sh 腳本bash
# 增長可執行權限 ➜ chmod u+x helloWorld.sh # 運行腳本 ➜ ./helloWorld.sh 或 ➜ sh hellowWorld.sh
單行註釋函數
#
開頭的行是註釋多行註釋測試
{}
括起來,定義成一個函數,沒有地方調用即達到註釋的效果。方式二:命令行
:<<EOF 註釋內容... 註釋內容... 註釋內容... EOF
變量定義日誌
=
兩邊不能有空格;help
命令查看保留關鍵字)。# 示例 VAR1="whoru" VAR2=100 var3=/data/www var4_name="root"
$VAR1
或 $(var1)
,其中,加花括號是爲了幫助解釋器識別變量的邊界。readonly VAR1
unset VAR1
局部、全局變量code
local
定義局部變量。值用雙引號 ""
或單引號 ''
表示orm
單引號單限制:
雙引號的優勢:
其它
# 字符串拼接 name="xiaoming" var2="hello, "$name # 輸出 hello, xiaoming # 獲取字符串長度 string="abcd" echo ${#string} # 輸出 4 echo `expr length "$string"` # 輸出 4 # 提取子字符串 msg="zhangsan is a good man" echo ${msg:1:4} # 輸出 hang echo ${msg: -3} # 輸出 man
定義:
array1=(value0 value1 value2 value3) # 或 array2[0]=value0 array2[1]=value1 array2[2]=value2
讀取
# 指定下標的元素 ➜ echo ${array2[2]}; // 輸出 value2 # 獲取數組全部元素 ➜ echo ${array2[*]}; // 輸出 value0 value1 value2 ➜ echo ${array2[@]}
獲取數組元素個數
➜ echo ${#array2[@]}; // 輸出 3 ➜ echo ${#array2[*]};
取得數組中指定下標元素的字符長度
➜ echo ${#array2[2]};
在執行 Shell 腳本時,能夠向腳本傳遞參數,腳本內獲取參數的格式爲 $n
,這裏的 n 指傳遞給腳本的第 n 個參數。
以下腳本文件 demo.sh
:
#!/bin/bash echo "執行的文件名:$0"; echo "第一個參數爲:$1"; echo "第二個參數爲:$2"; echo "第三個參數爲:$3";
執行該文件,並傳遞參數,以下:
➜ ./demo3.sh param1 param2 param3 執行的文件名:./demo3.sh 第一個參數爲:param1 第二個參數爲:param2 第三個參數爲:param3
其中,$0
是一個特殊變量,表明當前腳本文件名,還有幾個相似的變量以下:
變量 | 說明 |
---|---|
$# | 傳遞給腳本的參數個數。 |
$* | 以一個單字符串的形式顯示全部向腳本傳遞的參數,如 "$1 $2 ... $n" |
$@ | 與 $* 相同,可是使用引號把每一個參數包裹起來,如 "$1" "$2" ... "$n" |
$? | 最後一個執行的命令的退出狀態:0 正常;1 或其它任何值,表示有錯誤 |
$$ | 腳本運行的當前進程ID號 |
$! | 最後一個後臺命令的進程號。 |
原生 bash 不支持簡單的數學運算,可是能夠經過其餘命令來實現,例如 awk 和 expr,其中 expr 最經常使用。
假定有兩個變量:a=10
b=20
運算符 | 說明 | 舉例 |
---|---|---|
+ |
加法 | `expr $a + $b` 結果爲 30。 |
- |
減法 | `expr $a - $b` 結果爲 -10。 |
* |
乘法 | `expr $a \* $b` 結果爲 200。 |
/ |
除法 | `expr $b / $a` 結果爲 2。 |
% |
取餘 | `expr $b % $a` 結果爲 0。 |
= |
賦值 | a=$b 將把變量 b 的值賦給 a。 |
== |
用於比較兩個數字是否相同 | [ $a == $b ] 返回 false。 |
!= |
用於比較兩個數字是否不相同 | [ $a != $b ] 返回 true。 |
注意:
2+2
是錯誤的,必須寫成 2 + 2
; ` `
包裹起來;關係運算符只支持數字,不支持字符串,除非字符串的值是數字。
假定有兩個變量:a=10
b=20
運算符 | 說明 | 舉例 |
---|---|---|
-eq |
檢測兩個數是否相等 | [ $a -eq $b ] 返回 false。 |
-ne |
檢測兩個數是否不相等 | [ $a -ne $b ] 返回 true。 |
-gt |
檢測左邊的數是否大於右邊的 | [ $a -gt $b ] 返回 false。 |
-lt |
檢測左邊的數是否小於右邊的 | [ $a -lt $b ] 返回 true。 |
-ge |
檢測左邊的數是否大於等於右邊的 | [ $a -ge $b ] 返回 false。 |
-le |
檢測左邊的數是否小於等於右邊的 | [ $a -le $b ] 返回 true。 |
假定有兩個變量:a=10
b=20
運算符 | 說明 | 舉例 |
---|---|---|
! |
非運算,表達式爲 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。 |
假定有兩個變量:a=10
b=20
運算符 | 說明 | 舉例 |
---|---|---|
&& | 邏輯的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 邏輯的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
假定有兩個變量:a="abc"
b="efg"
運算符 | 說明 | 舉例 |
---|---|---|
= |
檢測兩個字符串是否相等 | [ $a = $b ] 返回 false。 |
!= |
檢測兩個字符串是否不相等 | [ $a != $b ] 返回 true。 |
-z |
檢測字符串長度是否爲 0(空) | [ -z $a ] 返回 false。 |
-n |
檢測字符串長度是否不爲0(非空) | [ -n "$a" ] 返回 true。 |
str | 檢測字符串是否爲不爲空 | [ $a ] 返回 true。 |
運算符 | 說明(若是是,則返回 true) | 舉例 |
---|---|---|
-b |
檢測文件是不是塊設備文件 | [ -b $file ] |
-c |
檢測文件是不是字符設備文件 | [ -c $file ] |
-d |
檢測文件是不是目錄 | [ -d $file ] |
-f |
檢測文件是不是普通文件(既不是目錄,也不是設備文件) | [ -f $file ] |
-g |
檢測文件是否設置了 SGID 位 | [ -g $file ] |
-k |
檢測文件是否設置了粘着位(Sticky Bit) | [ -k $file ] |
-p |
檢測文件是不是有名管道 | [ -p $file ] |
-u |
檢測文件是否設置了 SUID 位 | [ -u $file ] |
-r |
檢測文件是否可讀 | [ -r $file ] |
-w |
檢測文件是否可寫 | [ -w $file ] |
-x |
檢測文件是否可執行 | [ -x $file ] |
-s |
檢測文件是否爲非空(文件大小是否大於0)文件 | [ -s $file ] |
-e |
檢測文件(包括目錄)是否存在 | [ -e $file ] |
大多使用關係運算符檢查關係
# 語法格式 if condition1 then command1 ... elif condition2 then command2 else commandN fi
# 語法格式 case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; *) commandDefault ;; esac
用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令一般爲測試條件。其格式爲:
# 語法格式 while condition do command done
執行一系列命令直至條件爲 true 時中止,它與 while 循環
在處理方式上恰好相反。
# 語法格式 until condition do command done
# 語法格式 for var in item1 item2 ... itemN do command1 command2 ... commandN done
# 語法1 while : do command done # 語法2 while true do command done # 語法3 for (( ; ; ))
break
跳出整個循環,執行循環體後面的代碼,支持 break n
退出多層嵌套循環continue
結束當前循環,一樣支持 continue n
退出多層命令 | 說明 |
---|---|
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 之間的內容做爲輸入。 |
關於文件描述符:
0
一般是標準輸入(STDIN),Unix程序默認從 stdin
讀取數據。1
標準輸出(STDOUT),Unix程序默認向 stdout
輸出數據。2
標準錯誤輸出(STDERR),Unix程序會向 stderr
流中寫入錯誤信息。示例:
# 將 stdout 和 stderr 合併後重定向到 file ➜ command > file 2>&1
這是一個特殊的文件,寫入到它的內容都會被丟棄;若是嘗試從該文件讀取內容,也什麼也讀不到。咱們一般將命令的輸出重定向到它,起到「禁止輸出」的效果。
如:
# 屏蔽 stdout 和 stderr ➜ command > /dev/null 2>&1
# 將兩個 delimiter 之間的內容(document) 做爲輸入傳遞給 command。 command << delimiter document delimiter
說明:
delimiter
必定要頂格寫,前面不能有任何字符,後面也不能有任何字符,包括空格和 tab 縮進。delimiter
先後的空格會被忽略掉。[ function ] funcName [()] { command; [return int;] }
說明:
function
關鍵字非必須;return
函數返回值
echo
輸出一個字符串做爲函數的返回值。funcName
;func() { echo "第一個參數爲 $1 !" echo "第二個參數爲 $2 !" ... echo "第十個參數爲 ${10} !" ... } # 調用並傳參 func param1 param2 param3
說明:
$n
的形式來獲取參數的值,例如:$1 表示第一個參數,$2 表示第二個參數;${n}
來獲取參數。一般咱們將公用的函數抽離到單獨文件,以便重複調用,減小冗餘代碼。
對於一個函數庫文件:
.lib
進行標識;#!/bin/echo
輸出警告信息,避免用戶執行。示例:
#!/bin/echo # /home/user1/lib/comm_function.lib function add { echo "`expr $1 + $2`" }
#!/bin/bash # /home/user1/test.sh # 引入函數庫文件 # 使用絕對 或 相對路徑 . ./lib/comm_function.lib # 使用文件中的函數 add 1 3
➜ sh -x test_functions.sh + . ./lib/comm_function.lib + add 1 3 ++ expr 1 + 3 + echo 4 4
語法:find [路徑] [選項] [操做]
選項 | 說明 | 選項 | 說明 |
---|---|---|---|
-name |
文件名 | -iname |
文件名(忽略大小寫) |
-perm 777 |
文件權限 | -type f|d|l|c|b|p |
文件類型 |
-user |
文件屬主 | -nouser |
無有效屬主 |
-group |
文件屬組 | -nogroup |
無有效屬組 |
-size -n|+n |
文件大小 | -prune |
排除某些查找目錄(一般與 -path 一同使用) |
-mindepth n |
從 n 級子目錄開始查找 | -maxdepth n |
最多搜索到 n 級子目錄 |
-mtime -n|+n |
文件修改時間(天) | -mmin -n|+n |
文件修改時間(分鐘) |
-newer file1 |
文件修改時間比 file1 早 |
示例:
# 文件名 ➜ find /etc/ -name '*.conf' # 文件類型 # f 文件;d 目錄;c 字符設備文件; # b 塊設備文件;l 連接文件;p 管道文件 ➜ find /etc/ -type f # 文件大小 # -n 小於等於;+n 大於等於 ➜ find . -size +100M ➜ find . -size -10k # 文件修改時間 # -n < n天之內修改過的文件; # n = n 天修改過得文件; # +n > n天之外修改過的文件; ➜ find . -mtime -3 ➜ find . -mtime 3 ➜ find . -mtime +3 # 排除目錄 # -path ./test1 -prune 排除 test1 目錄 # -path ./test2 -prune 排除 test2 目錄 # -o type f 固定結尾寫法 ➜ find . -path ./test1 -prune -o -path ./test2 -prune -o type f
-print
打印輸出-exec 'command' {} \;
其中 {}
是前面查找匹配到的結果-ok
與 exec 功能同樣,但每次操做都給用戶提示,由用戶決定是否執行對應的操做。示例:
# 查找 30 天之前的日誌文件並刪除 ➜ find /var/log -name '*.log' -mtime +30 -exec rm -f {} \; # 查找全部 .conf 文件,並移動到指定目錄 ➜ find /etc/apache -name '*.conf' -exec cp {} /home/user1/backup \;
用於字符串的輸出,基本格式 echo string
。
使用示例:
# 顯示普通字符 ➜ echo "It is a test" # 輸出 It is a test # 顯示轉義字符 ➜ echo "\"It is a test\"" # 輸出 "It is a test" # 顯示變量 #!/bin/sh NAME="xiaoming" ➜ echo "$NAME It is a test" # 輸出 xiaoming is a test # 顯示換行 ➜ echo -e "OK! \n" # -e 開啓轉義 ➜ echo "It is a test" # 顯示不換行 ➜ echo -e "OK! \c" # -e 開啓轉義 \c 不換行 ➜ echo "It is a test" # 顯示結果定向至文件 ➜ echo "It is a test" > myfile # 顯示命令執行結果 ➜ echo `date`
模仿 C 程序庫(library)裏的 printf() 程序,主要用於格式化輸出。
默認 printf
不會像 echo
自動添加換行符,咱們能夠手動添加 \n
。
其基本語法格式爲:
➜ printf format-string [arguments...]
說明:
format-string
爲格式控制字符串arguments
爲參數列表。示例:
➜ printf "%-10s %-8s %-4s\n" 姓名 性別 體重kg ➜ printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234 ➜ printf "%-10s %-8s %-4.2f\n" 楊過 男 48.6543 ➜ printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876 姓名 性別 體重kg 郭靖 男 66.12 楊過 男 48.65 郭芙 女 47.99
其中:
%s
%c
%d
%f
都是格式替代符;%-10s
指一個寬度爲10個字符(-表示左對齊,沒有則表示右對齊),任何字符都會被顯示在10個字符寬的字符內,若是不足則自動以空格填充,超過也會將內容所有顯示出來。%-4.2f
指格式化爲小數,其中.2指保留2位小數。更多使用示例:
# 沒有引號也能夠輸出 ➜ printf %s abcdef # 格式只指定了一個參數,但多出的參數仍然會按照該格式輸出,format-string 被重用 ➜ printf %s abc def abcdef ➜ printf "%s\n" abc def abc def # 若是沒有 arguments,那麼 %s 用NULL代替,%d 用 0 代替 ➜ printf "%s and %d \n" and 0
用於檢查某個條件是否成立,它能夠進行數值、字符和文件三個方面的測試(詳見第3節對應的運算符部分)。
基本使用示例:
cd /bin if test -e ./bash then echo '文件已存在!' else echo '文件不存在!' fi
規則 | 說明 | 示例 var="Hello shell" |
---|---|---|
${變量#匹配規則} |
從頭開始匹配,最短刪除 | ${var#*e} => llo shell |
${變量##匹配規則} |
從頭開始匹配,最長刪除 | ${var##*e} => ll |
${變量%匹配規則} |
從尾開始匹配,最短刪除 | ${var%e*} => Hello sh |
${變量%%匹配規則} |
從尾開始匹配,最長刪除 | ${var%%e*} => H |
${變量/舊字符串/新字符串} |
只替換匹配到的第一個 | ${var/e/*} => H*llo shell |
${變量//舊字符串/新字符串} |
所有替換 | ${var//e/*} => H*llo sh*ll |
shell 中變量默認都是字符串,除非使用如下方式聲明。
declare 或 typeset 參數 | 說明 |
---|---|
-r | 只讀 |
-i | 整數 |
-a | 數組 |
-f | 在腳本中顯示定義的函數和內容 |
-F | 在腳本中顯示定義的函數 |
-X | 將變量聲明爲環境變量 |
示例:
➜ declare -r var1="hello shell type" ➜ var1="hello lalala" zsh: read-only variable: var1
系統內置,支持 +
、-
、*
、/
、^ 指數
、% 取餘
,並使用 scale
指定小數位數,默認 0
。
示例:
➜ which bc /usr/bin/bc # 示例 ➜ echo "5+4" | bc 9 ➜ echo "5-4" | bc 1 ➜ echo "5*4" | bc 20 ➜ echo "5/4" | bc 1 ➜ echo "scale=3;5/4" | bc 1.250 ➜ echo "5%4" | bc 1 ➜ echo "5^4" | bc 625
[[
是關鍵字,許多 shell 並不支持這種方式。
&&
, ||
, <
和 >
操做符能在一個 [[ ... ]]
測試裏經過,但在 [ ... ]
結構會發生錯誤。[
是一條命令,與 test 等價,大多數的 shell 都支持。
>
與 <
必須轉義,不然就變成 IO 重定向操做符了。