01 shell程式設計之變數定義

nice_xm發表於2020-07-22

一、SHELL介紹

㈠ 什麼是shell指令碼?

簡單來說就是將需要執行的命令儲存到文字中,按照順序執行。它是解釋型的,意味著不需要編譯。
若干命令 + 指令碼的基本格式 + 指令碼特定語法 + 思想= shell指令碼

㈡ 什麼時候用到指令碼?

重複化、複雜化的工作,通過把工作的命令寫成指令碼,以後僅僅需要執行指令碼就能完成這些工作。

㈢ shell指令碼能幹啥?

①自動化軟體部署	LAMP/LNMP/Tomcat...
②自動化管理	系統初始化指令碼、批量更改主機密碼、推送公鑰...
③自動化分析處理	統計網站訪問量
④自動化備份	資料庫備份、日誌轉儲...
⑤自動化監控指令碼

㈣ 如何學習shell指令碼?

儘可能記憶更多的命令(記憶命令使用功能和場景)
掌握指令碼的標準的格式(指定魔法位元組、使用標準的執行方式執行指令碼)
必須==熟悉掌握==指令碼的基本語法(重點)

㈤ 學習shell指令碼的祕訣

多看(看懂)——>模仿(多練)——>多思考(多寫)

㈥ shell指令碼的基本寫法

  1. 指令碼第一行
魔法字元==#!==指定直譯器【必寫】
#!/bin/bash 表示以下內容使用bash直譯器解析
注意: 如果直接將直譯器路徑寫死在指令碼里,可能在某些系統就會存在找不到直譯器的相容性問題,所以可以使用:#!/bin/env 直譯器 #!/bin/env bash

2)指令碼第二部分,註釋(#號)說明,對指令碼的基本資訊進行描述【可選】

#!/bin/env bash
# 以下內容是對指令碼的基本資訊的描述
# Name: 名字
# Desc:描述describe
# Path:存放路徑
# Usage:用法
# Update:更新時間

#下面就是指令碼的具體內容
commands
...

3)指令碼第三部分,指令碼要實現的具體程式碼內容

㈦ shell指令碼的執行方法

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. 變數是什麼?

一句話概括:變數是用來臨時儲存資料的,該資料是可以變化的資料。

  1. 什麼時候需要定義變數?

如果某個內容需要多次使用,並且在程式碼中重複出現,那麼可以用變數代表該內容。這樣在修改內容的時候,僅僅需要修改變數的值。
在程式碼運作的過程中,可能會把某些命令的執行結果儲存起來,後續程式碼需要使用這些結果,就可以直接使用這個變數。

  1. 變數如何定義?

*變數名=====變數值*
變數名:用來臨時儲存資料的
變數值:就是臨時的可變化的資料

[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			從此,我單身了,你可以給我介紹任何人

  1. 變數的定義規則

雖然可以給變數(變數名)賦予任何值;但是,對於變數名也是要求的!?
㈠ 變數名區分大小寫

[root@mpd~]# A=hello
[root@mpd~]# a=world
[root@mpd~]# echo $A
hello
[root@mpd~]# echo $a
world

㈡ 變數名不能有特殊符號

[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

㈢ 變數名不能以數字開頭

[root@mpd~]# 1A=hello
-bash: 1A=hello: command not found
[root@mpd~]# A1=hello
注意:不能以數字開頭並不代表變數名中不能包含數字呦

㈣ 等號兩邊不能有任何空格

[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

㈤ 變數名儘量做到見名知意

NTP_IP=10.1.1.1
DIR=/u01/app1
TMP_FILE=/var/log/1.log
...
說明:一般變數名使用大寫(小寫也可以),不要同一個指令碼中變數全是a,b,c等不容易閱讀
  1. 變數的定義方式有哪些?
    ㈠ 基本方式
# 直接賦值給一個變數
[root@mpd~]# A=1234567
[root@mpd~]# echo $A
1234567
[root@mpd~]# echo ${A:2:4}		表示從A變數中第3個字元開始擷取,擷取4個字元
3456

說明:
$變數名 和 ${變數名}的異同
相同點:都可以呼叫變數
不同點:${變數名}可以只擷取變數的一部分,而$變數名不可以

㈡ 命令執行結果賦值給變數

[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 [選項] 變數名
常見選項

選項	# 釋義
-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 選項 變數名=變數值
常用選項:


選項	釋義	舉例
-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
  1. 變數的分類
    ㈠ 本地變數
    本地變數:當前使用者自定義的變數。當前程式中有效,其他程式及當前程式的子程式無效。
    ㈡ 環境變數
    環境變數:當前程式有效,並且能夠被子程式呼叫。
    env檢視當前使用者的環境變數
    set查詢當前使用者的所有變數(臨時變數與環境變數)
    export 變數名=變數值 或者 變數名=變數值;export 變數
[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讓其生效或者退出重新登入。
使用者登入系統讀取相關檔案的順序

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}

#!/bin/bash
#瞭解shell內建變數中的位置引數含義
echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1" 
echo "\$2 = $2" 
echo "\$3 = $3" 
echo "\$11 = ${11}" 
echo "\$12 = ${12}"

進一步瞭解$和​$@的區別
$
:表示將變數看成一個整體 $@:表示變數是獨立的

#!/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. 四則運算子號

表示式	舉例
$(( ))	echo $((1+1))
$[ ]	echo $[10-5]
expr	expr 10 / 5
let	n=1;let n+=1 等價於 let n=n+1

2.瞭解i和i
對變數的值的影響

[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

對錶達式的值的影響

[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. 陣列定義
    ㈠ 陣列分類
    普通陣列:只能使用整數作為陣列索引(元素的下標)
    關聯陣列:可以使用字串作為陣列索引(元素的下標)
    ㈡ 普通陣列定義
    一次賦予一個值
陣列名[索引下標]=值
array[0]=v1
array[1]=v2
array[2]=v3
array[3]=v4

一次賦予多個值

陣列名=(值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)

㈢ 陣列的讀取

${陣列名[元素下標]}

echo ${array[0]}			獲取陣列裡第一個元素
echo ${array[*]}			獲取陣列裡的所有元素
echo ${#array[*]}			獲取陣列裡所有元素個數
echo ${!array[@]}    	獲取陣列元素的索引下標
echo ${array[@]:1:2}    訪問指定的元素;1代表從下標為1的元素開始獲取;2代表獲取後面幾個元素

檢視普通陣列資訊:
[root@mpd~]# declare -a

㈣ 關聯陣列定義
①首先宣告關聯陣列
declare -A asso_array1

declare -A asso_array1
declare -A asso_array2
declare -A asso_array3

② 陣列賦值
一次賦一個值

陣列名[索引or下標]=變數值
# asso_array1[linux]=one
# asso_array1[java]=two
# asso_array1[php]=three

一次賦多個值

asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="mpd")

檢視關聯陣列

# declare -A
declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )'
declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="mpd" )'

獲取關聯陣列值

# 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

其他定義方式

[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" )
  1. 其他變數定義
    取出一個目錄下的目錄和檔案:dirname和 basename
# A=/root/Desktop/shell/mem.txt 
# echo $A
/root/Desktop/shell/mem.txt
# dirname $A   取出目錄
/root/Desktop/shell
# basename $A  取出檔案
mem.tx

-變數"內容"的刪除和替換

一個“%”代表從右往左刪除
兩個“%%”代表從右往左去掉最多
一個“#”代表從左往右去掉刪除
兩個“##”代表從左往右去掉最多

舉例說明:
# url=www.taobao.com
# echo ${#url}		     獲取變數的長度
# echo ${url#*.}
# echo ${url##*.}
# echo ${url%.*}
# echo ${url%%.*}

以下了解,自己完成

# 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

${變數名:?新的變數值}
變數沒有被賦值或者賦空值時:提示錯誤資訊
變數被賦值:不會使用“新的變數值“ 替代

說明:?主要是當變數沒有賦值提示錯誤資訊的,沒有賦值功能

相關文章