1. 程式人生 > >01 shell程式設計之變數定義

01 shell程式設計之變數定義

#### 一、SHELL介紹 ㈠ 什麼是shell指令碼? ```bash 簡單來說就是將需要執行的命令儲存到文字中,按照順序執行。它是解釋型的,意味著不需要編譯。 若干命令 + 指令碼的基本格式 + 指令碼特定語法 + 思想= shell指令碼 ``` ㈡ 什麼時候用到指令碼? ```bash 重複化、複雜化的工作,通過把工作的命令寫成指令碼,以後僅僅需要執行指令碼就能完成這些工作。 ``` ㈢ shell指令碼能幹啥? ```bash ①自動化軟體部署 LAMP/LNMP/Tomcat... ②自動化管理 系統初始化指令碼、批量更改主機密碼、推送公鑰... ③自動化分析處理 統計網站訪問量 ④自動化備份 資料庫備份、日誌轉儲... ⑤自動化監控指令碼 ``` ㈣ 如何學習shell指令碼? ```bash 儘可能記憶更多的命令(記憶命令使用功能和場景) 掌握指令碼的標準的格式(指定魔法位元組、使用標準的執行方式執行指令碼) 必須==熟悉掌握==指令碼的基本語法(重點) ``` ㈤ 學習shell指令碼的祕訣 ```bash 多看(看懂)——>模仿(多練)——>多思考(多寫) ``` ㈥ shell指令碼的基本寫法 1) 指令碼第一行 ```bash 魔法字元==#!==指定直譯器【必寫】 #!/bin/bash 表示以下內容使用bash直譯器解析 注意: 如果直接將直譯器路徑寫死在腳本里,可能在某些系統就會存在找不到直譯器的相容性問題,所以可以使用:#!/bin/env 直譯器 #!/bin/env bash ``` 2)指令碼第二部分,註釋(#號)說明,對指令碼的基本資訊進行描述【可選】 ```bash #!/bin/env bash # 以下內容是對指令碼的基本資訊的描述 # Name: 名字 # Desc:描述describe # Path:存放路徑 # Usage:用法 # Update:更新時間 #下面就是指令碼的具體內容 commands ... ``` 3)指令碼第三部分,指令碼要實現的具體程式碼內容 ㈦ shell指令碼的執行方法 ```bash 1) 編寫人生第一個shell指令碼 [root@mpd]# cat first_shell.sh #!/bin/env bash # 以下內容是對指令碼的基本資訊的描述 # Name: first_shell.sh # Desc: num1 # Path: /shell01/first_shell.sh # Usage:/shell01/first_shell.sh # Update:2019-05-05 echo "hello world" echo "hello world" echo "hello world" 2) 指令碼增加可執行許可權 [root@mpd]# chmod +x first_shell.sh 3) 標準方式執行指令碼 [root@mpd]# pwd /shell01 [root@mpd]# /shell01/first_shell.sh 或者 [root@mpd]# ./first_shell.sh 注意:標準執行方式指令碼必須要有可執行許可權。 1. 直接俄在命令列指定直譯器執行 [root@mpd]# bash first_shell.sh [root@mpd]# sh first_shell.sh [root@mpd]# bash -x first_shell.sh + echo 'hello world' hello world + echo 'hello world' hello world + echo 'hello world' hello world ---------------- -x:一般用於排錯,檢視指令碼的執行過程 -n:用來檢視指令碼的語法是否有問題 ------------ 2. 使用source命令讀取指令碼檔案,執行檔案裡的程式碼 [root@mpd]# source first_shell.sh hello world hello world hello world ``` #### 二、變數的定義 1. 變數是什麼? >一句話概括:變數是用來臨時儲存資料的,該資料是可以變化的資料。 2. 什麼時候需要定義變數? >如果某個內容需要多次使用,並且在程式碼中重複出現,那麼可以用變數代表該內容。這樣在修改內容的時候,僅僅需要修改變數的值。 在程式碼運作的過程中,可能會把某些命令的執行結果儲存起來,後續程式碼需要使用這些結果,就可以直接使用這個變數。 3. 變數如何定義? >*變數名=====變數值* 變數名:用來臨時儲存資料的 變數值:就是臨時的可變化的資料 ```bash [root@mpd~]# A=hello 定義變數A [root@mpd~]# echo $A 呼叫變數A,要給錢的,不是人民幣是美元"$" hello [root@mpd~]# echo ${A} 還可以這樣呼叫,不管你的姿勢多優雅,總之要給錢 hello [root@mpd~]# A=world 因為是變數所以可以變,移情別戀是常事 [root@mpd~]# echo $A 不管你是誰,只要呼叫就要給錢 world [root@mpd~]# unset A 不跟你玩了,取消變數 [root@mpd~]# echo $A 從此,我單身了,你可以給我介紹任何人 ``` 4. 變數的定義規則 >雖然可以給變數(變數名)賦予任何值;但是,對於變數名也是要求的!:unamused: ㈠ 變數名區分大小寫 ```bash [root@mpd~]# A=hello [root@mpd~]# a=world [root@mpd~]# echo $A hello [root@mpd~]# echo $a world ``` ㈡ 變數名不能有特殊符號 ```bash [root@mpd~]# *A=hello -bash: *A=hello: command not found [root@mpd~]# ?A=hello -bash: ?A=hello: command not found [root@mpd~]# @A=hello -bash: @A=hello: command not found 特別說明:對於有空格的字串給變數賦值時,要用引號引起來 [root@MissHou ~]# A=hello world -bash: world: command not found [root@MissHou ~]# A="hello world" [root ``` ㈢ 變數名不能以數字開頭 ```bash [root@mpd~]# 1A=hello -bash: 1A=hello: command not found [root@mpd~]# A1=hello 注意:不能以數字開頭並不代表變數名中不能包含數字呦 ``` ㈣ 等號兩邊不能有任何空格 ```bash [root@mpd~]# A =123 -bash: A: command not found [root@mpd~]# A= 123 -bash: 123: command not found [root@mpd~]# A = 123 -bash: A: command not found [root@mpd~]# A=123 [root@mpd~]# echo $A 123 ``` ㈤ 變數名儘量做到見名知意 ```bash NTP_IP=10.1.1.1 DIR=/u01/app1 TMP_FILE=/var/log/1.log ... 說明:一般變數名使用大寫(小寫也可以),不要同一個指令碼中變數全是a,b,c等不容易閱讀 ``` 5. 變數的定義方式有哪些? ㈠ 基本方式 ```bash # 直接賦值給一個變數 [root@mpd~]# A=1234567 [root@mpd~]# echo $A 1234567 [root@mpd~]# echo ${A:2:4} 表示從A變數中第3個字元開始擷取,擷取4個字元 3456 說明: $變數名 和 ${變數名}的異同 相同點:都可以呼叫變數 不同點:${變數名}可以只擷取變數的一部分,而$變數名不可以 ``` ㈡ 命令執行結果賦值給變數 ```bash [root@mpd~]# B=`date +%F` [root@mpd~]# echo $B 2019-04-16 [root@mpd~]# C=$(uname -r) [root@mpd~]# echo $C 2.6.32-696.el6.x86_64 ``` ㈢ 互動式定義變數(read) **目的:**讓使用者自己給變數賦值,比較靈活。 語法:read [選項] 變數名 **常見選項** ```bash 選項 # 釋義 -p # 定義提示使用者的資訊 -n # 定義字元數(限制變數值的長度) -s # 不顯示(不顯示使用者輸入的內容) -t # 定義超時時間,預設單位為秒(限制使用者輸入變數值的超時時間 用法1:使用者自己定義變數值 # 例項 [root@mpd~]# read name harry [root@mpd~]# echo $name harry [root@mpd~]# read -p "Input your name:" name Input your name:tom [root@mpd~]# echo $name tom # 用法2:變數值來自檔案 [root@mpd~]# cat 1.txt 10.1.1.1 255.255.255.0 [root@mpd~]# read ip mask < 1.txt [root@mpd~]# echo $ip 10.1.1.1 [root@mpd~]# echo $mask 255.255.255.0 ``` ㈣ 定義有型別的變數(declare) 目的: 給變數做一些限制,固定變數的型別,比如:整型、只讀 用法:declare 選項 變數名=變數值 常用選項: ```bash 選項 釋義 舉例 -i 將變數看成整數 declare -i A=123 -r 定義只讀變數 declare -r B=hello -a 定義普通陣列;檢視普通陣列 -A 定義關聯陣列;檢視關聯陣列 -x 將變數通過環境匯出 declare -x AAA=123456 等於 export AAA=123456 [root@mpd~]# declare -i A=123 [root@mpd~]# echo $A 123 [root@mpd~]# A=hello [root@mpd~]# echo $A 0 [root@mpd~]# declare -r B=hello [root@mpd~]# echo $B hello [root@mpd~]# B=world -bash: B: readonly variable [root@mpd~]# unset B -bash: unset: B: cannot unset: readonly variable ``` 6. 變數的分類 ㈠ 本地變數 本地變數:當前使用者自定義的變數。當前程序中有效,其他程序及當前程序的子程序無效。 ㈡ 環境變數 環境變數:當前程序有效,並且能夠被子程序呼叫。 env檢視當前使用者的環境變數 set查詢當前使用者的所有變數(臨時變數與環境變數) export 變數名=變數值 或者 變數名=變數值;export 變數 ```bash [root@mpd~]# export A=hello 臨時將一個本地變數(臨時變數)變成環境變數 [root@mpd~]# env|grep ^A A=hello 永久生效: vim /etc/profile 或者 ~/.bashrc export A=hello 或者 A=hello export A 說明:系統中有一個變數PATH,環境變數 export PATH=/usr/local/mysql/bin:$PATH ``` ㈢ 全域性變數 全域性變數:全域性所有的使用者和程式都能呼叫,且繼承,新建的使用者也預設能呼叫. 解讀相關配置檔案 檔名|說明|備註 ---|:---:|---: $HOME/.bashrc|當前使用者的bash資訊,使用者登入時讀取 定義別名、umask、函式等 $HOME/.bash_profile|當前使用者的環境變數,使用者登入時讀取 $HOME/.bash_logout|當前使用者退出當前shell時最後讀取 定義使用者退出時執行的程式等 /etc/bashrc|全域性的bash資訊,所有使用者都生效 /etc/profile|全域性環境變數資訊 系統和所有使用者都生效 $HOME/.bash_history|使用者的歷史命令 history -w 儲存歷史記錄 history -c 清空歷史記錄 **說明:**以上檔案修改後,都需要重新source讓其生效或者退出重新登入。 使用者登入系統讀取相關檔案的順序 ```bash 1 /etc/profile 2 $HOME/.bash_profile 3 $HOME/.bashrc 4 /etc/bashrc 5 $HOME/.bash_logout ``` ㈣ 系統變數 系統變數(內建bash中變數) : shell本身已經固定好了它的名字和作用. 內建變數|含義 ---|:---:|---: $? |上一條命令執行後返回的狀態;狀態值為0表示執行正常,非0表示執行異常或錯誤 $0 |當前執行的程式或指令碼名 $# |指令碼後面接的引數的個數 $* |指令碼後面所有引數,引數當成一個整體輸出,每一個變數引數之間以空格隔開 $@ |指令碼後面所有引數,引數是獨立的,也是全部輸出 $1~$9 |指令碼後面的位置引數,$1表示第1個位置引數,依次類推 ${10}~${n} |擴充套件位置引數,第10個位置變數必須用{}大括號括起來(2位數字以上擴起來) $$ |當前所在程序的程序號,如echo $$ $! |後臺執行的最後一個程序號 (當前終端) !$ |呼叫最後一條命令歷史中的引數 進一步瞭解位置引數$1~${n} ```bash #!/bin/bash #瞭解shell內建變數中的位置引數含義 echo "\$0 = $0" echo "\$# = $#" echo "\$* = $*" echo "\$@ = $@" echo "\$1 = $1" echo "\$2 = $2" echo "\$3 = $3" echo "\$11 = ${11}" echo "\$12 = ${12}" ``` 進一步瞭解$*和​$@的區別 $*:表示將變數看成一個整體 $@:表示變數是獨立的 ```bash #!/bin/bash for i in "$@" do echo $i done echo "======我是分割線=======" for i in "$*" do echo $i done [root@MissHou ~]# bash 3.sh a b c a b c ======我是分割線======= a b c ``` #### 三、簡單四則運算 算術運算:預設情況下,shell就只能支援簡單的整數運算 運算內容:加(+)、減(-)、乘(*)、除(/)、求餘數(%) 1. 四則運算子號 ```bash 表示式 舉例 $(( )) echo $((1+1)) $[ ] echo $[10-5] expr expr 10 / 5 let n=1;let n+=1 等價於 let n=n+1 ``` 2.瞭解i和i 對變數的值的影響 ```bash [root@mpd~]# i=1 [root@mpd~]# let i++ [root@mpd~]# echo $i 2 [root@mpd~]# j=1 [root@mpd~]# let ++j [root@mpd~]# echo $j 2 ``` 對錶達式的值的影響 ```bash [root@mpd~]# unset i j [root@mpd~]# i=1;j=1 [root@mpd~]# let x=i++ 先賦值,再運算 [root@mpd~]# let y=++j 先運算,再賦值 [root@mpd~]# echo $i 2 [root@mpd~]# echo $j 2 [root@mpd~]# echo $x 1 [root@mpd~]# echo $y 2 ``` 四、擴充套件補充 1. 陣列定義 ㈠ 陣列分類 普通陣列:只能使用整數作為陣列索引(元素的下標) 關聯陣列:可以使用字串作為陣列索引(元素的下標) ㈡ 普通陣列定義 一次賦予一個值 ```bash 陣列名[索引下標]=值 array[0]=v1 array[1]=v2 array[2]=v3 array[3]=v4 ``` 一次賦予多個值 ```bash 陣列名=(值1 值2 值3 ...) array=(var1 var2 var3 var4) array1=(`cat /etc/passwd`) 將檔案中每一行賦值給array1陣列 array2=(`ls /root`) array3=(harry amy jack "Miss Hou") array4=(1 2 3 4 "hello world" [10]=linux) ``` ㈢ 陣列的讀取 ```bash ${陣列名[元素下標]} echo ${array[0]} 獲取數組裡第一個元素 echo ${array[*]} 獲取數組裡的所有元素 echo ${#array[*]} 獲取數組裡所有元素個數 echo ${!array[@]} 獲取陣列元素的索引下標 echo ${array[@]:1:2} 訪問指定的元素;1代表從下標為1的元素開始獲取;2代表獲取後面幾個元素 檢視普通陣列資訊: [root@mpd~]# declare -a ``` ㈣ 關聯陣列定義 ①首先宣告關聯陣列 declare -A asso_array1 ```bash declare -A asso_array1 declare -A asso_array2 declare -A asso_array3 ``` ② 陣列賦值 一次賦一個值 ```bash 陣列名[索引or下標]=變數值 # asso_array1[linux]=one # asso_array1[java]=two # asso_array1[php]=three ``` 一次賦多個值 ```bash asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="mpd") ``` 檢視關聯陣列 ```bash # declare -A declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )' declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="mpd" )' ``` 獲取關聯陣列值 ```bash # echo ${asso_array1[linux]} one # echo ${asso_array1[php]} three # echo ${asso_array1[*]} three two one # echo ${!asso_array1[*]} php java linux # echo ${#asso_array1[*]} 3 # echo ${#asso_array2[*]} 4 # echo ${!asso_array2[*]} name3 name2 name1 name4 ``` 其他定義方式 ```bash [root@Mmpd]# declare -A books [root@mpd5]# let books[linux]++ [root@mpd]# declare -A|grep books declare -A books='([linux]="1" )' [root@mpd]# let books[linux]++ [root@mpd]# declare -A|grep books declare -A books='([linux]="2" ) ``` 2. 其他變數定義 取出一個目錄下的目錄和檔案:dirname和 basename ```bash # A=/root/Desktop/shell/mem.txt # echo $A /root/Desktop/shell/mem.txt # dirname $A 取出目錄 /root/Desktop/shell # basename $A 取出檔案 mem.tx ``` -變數"內容"的刪除和替換 ```bash 一個“%”代表從右往左刪除 兩個“%%”代表從右往左去掉最多 一個“#”代表從左往右去掉刪除 兩個“##”代表從左往右去掉最多 舉例說明: # url=www.taobao.com # echo ${#url} 獲取變數的長度 # echo ${url#*.} # echo ${url##*.} # echo ${url%.*} # echo ${url%%.*} ``` 以下了解,自己完成 ```bash # A=/root/Desktop/shell/mem.txt # echo $A /root/Desktop/shell/mem.txt # dirname $A 取出目錄 /root/Desktop/shell # basename $A 取出檔案 mem.txt -變數"內容"的刪除和替換 一個“%”代表從右往左刪除 兩個“%%”代表從右往左去掉最多 一個“#”代表從左往右去掉刪除 兩個“##”代表從左往右去掉最多 舉例說明: # url=www.taobao.com # echo ${#url} 獲取變數的長度 # echo ${url#*.} # echo ${url##*.} # echo ${url%.*} # echo ${url%%.*} 以下了解,自己完成 替換:/ 和 // 1015 echo ${url/ao/AO} 用AO代替ao(從左往右第一個) 1017 echo ${url//ao/AO} 貪婪替換(替代所有) 替代: - 和 :- +和:+ 1019 echo ${abc-123} 1020 abc=hello 1021 echo ${abc-444} 1022 echo $abc 1024 abc= 1025 echo ${abc-222} ${變數名-新的變數值} 或者 ${變數名=新的變數值} 變數沒有被賦值:會使用“新的變數值“ 替代 變數有被賦值(包括空值): 不會被替代 1062 echo ${ABC:-123} 1063 ABC=HELLO 1064 echo ${ABC:-123} 1065 ABC= 1066 echo ${ABC:-123} ${變數名:-新的變數值} 或者 ${變數名:=新的變數值} 變數沒有被賦值或者賦空值:會使用“新的變數值“ 替代 變數有被賦值: 不會被替代 1116 echo ${abc=123} 1118 echo ${abc:=123} [root@mpd~]# unset abc [root@mpd~]# echo ${abc:+123} [root@mpd~]# abc=hello [root@mpd~]# echo ${abc:+123} 123 [root@mpd~]# abc= [root@mpd~]# echo ${abc:+123} ${變數名+新的變數值} 變數沒有被賦值或者賦空值:不會使用“新的變數值“ 替代 變數有被賦值: 會被替代 [root@mpd~]# unset abc [root@mpd~]# echo ${abc+123} [root@mpd~]# abc=hello [root@mpd~]# echo ${abc+123} 123 [root@mpd~]# abc= [root@mpd~]# echo ${abc+123} 123 ${變數名:+新的變數值} 變數沒有被賦值:不會使用“新的變數值“ 替代 變數有被賦值(包括空值): 會被替代 [root@mpd~]# unset abc [root@mpd~]# echo ${abc?123} -bash: abc: 123 [root@mpd~]# abc=hello [root@mpd~]# echo ${abc?123} hello [root@mpd~]# abc= [root@mpd~]# echo ${abc?123} ${變數名?新的變數值} 變數沒有被賦值:提示錯誤資訊 變數被賦值(包括空值):不會使用“新的變數值“ 替代 [root@mpd~]# unset abc [root@mpd~]# echo ${abc:?123} -bash: abc: 123 [root@mpd~]# abc=hello [root@mpd~]# echo ${abc:?123} hello [root@mpd~]# abc= [root@mpd~]# echo ${abc:?123} -bash: abc: 123 ${變數名:?新的變數值} 變數沒有被賦值或者賦空值時:提示錯誤資訊 變數被賦值:不會使用“新的變數值“ 替代 說明:?主要是當變數沒有賦值提示錯誤資訊的,沒有賦值