01 shell程式設計之變數定義
阿新 • • 發佈:2020-07-22
#### 一、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
${變數名:?新的變數值}
變數沒有被賦值或者賦空值時:提示錯誤資訊
變數被賦值:不會使用“新的變數值“ 替代
說明:?主要是當變數沒有賦值提示錯誤資訊的,沒有賦值