Shell程式設計-03-Shell中的特殊變數和擴充套件變數
特殊變數
在Shell中的特殊變數主要分別兩種位置引數變數、狀態變數兩種。
位置引數變數
Shell中的位置引數變數主要是指$0、$1、$#等,主要用於從命令列、函式或指令碼執行等地方傳遞引數。詳細說明如下所示:
- $0:獲取當前執行的Shell指令碼的檔名,如指令碼中包含路徑,則輸出也包括路徑
- $n:獲取當前執行的Shell指令碼的第n個引數值,如n>9,則需要使用用大括號,如${10},各引數間用空格進行分隔
- $#:獲取當前執行的Shell指令碼傳入引數的總個數
- $*:獲取當前執行的Shell所有傳入引數,如不加引號則與[email protected]
- [email protected]:獲取當前執行的Shell所有傳入引數,**如不加引號則與$*功能相同,如果新增雙引號"[email protected]",則表示將所有傳入引數視為獨立的字串**,相當於"$1" "$2" "$3"
當"$*"和"[email protected]"都新增雙引號時,兩者的功能有所區別;如不加,則功能相同,無區別。
位置引數變數示例
1、示例一:
[[email protected] Test]# cat para.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
echo '$0 is:' $0
echo '$1 is:' $1
echo '$12 is:' ${12}
echo '$# is:' $#
echo '$* is:' $*
echo '"$*"is:' "$*"
echo ' [email protected] is:' [email protected]
echo '"[email protected]"is:' "[email protected]"
# 輸出結果
[[email protected]st Test]# bash ~/Test/para.sh {a..z}
a b c d e f g h i j k l m n o
$0 is: /root/Test/para.sh
$1 is: a
$12 is: l
$# is: 26
$* is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"$*"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
[email protected] is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"[email protected]"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
1、傳入的引數個數多於指令碼定義的引數時,則多出的引數會忽略
2、傳入的引數中如使用雙引號,則會當作一個引數值進行傳遞
3、位置引數如大於9,需要使用${}進行傳遞
2、示例二:
[[email protected] Test]# cat testposition.sh
#!/bin/bash
echo '$# $1 $2 $3 $* [email protected]'
echo $# $1 $2 $3 $* [email protected]
echo "************"
echo '$*'
for tmp in $*
do
echo $tmp
done
echo "************"
echo "@@@@@@@@@@@@"
echo '[email protected]'
for temp in [email protected]
do
echo $temp
done
echo "@@@@@@@@@@@@"
echo '"*"*"*"*"*"*'
echo '$*'
for i in "$*"
do
echo $i
done
echo '"*"*"*"*"*"*'
echo '"@"@"@"@"@"@'
echo '[email protected]'
for j in "[email protected]"
do
echo $j
done
echo '"@"@"@"@"@"@'
[[email protected] Test]# bash testposition.sh "Hello Jack" Welcome "to Shanghai"
$# $1 $2 $3 $* [email protected]
3 Hello Jack Welcome to Shanghai Hello Jack Welcome to Shanghai Hello Jack Welcome to Shanghai
************
$* # 未加雙引號,所以會輸出全部引數,則第一個和第三個引數會拆開
Hello
Jack
Welcome
to
Shanghai
************
@@@@@@@@@@@@
[email protected] # 未加雙引號,所以會輸出全部引數,則第一個和第三個引數會拆開
Hello
Jack
Welcome
to
Shanghai
@@@@@@@@@@@@
"*"*"*"*"*"*
$* # 新增雙引號後,傳入的引數全部當一個引數進行輸出
Hello Jack Welcome to Shanghai
"*"*"*"*"*"*
"@"@"@"@"@"@
[email protected] # 新增雙引號後,傳入的引數全部當獨立的引數進行輸出
Hello Jack
Welcome
to Shanghai
"@"@"@"@"@"@
狀態變數
- $?:獲取上一個命令或指令碼的執行狀態值(0:成功,其他:失敗)
- $$:獲取當前執行的Shell的程序號(PID)
- $!:獲取上一個在後臺工作的程序的程序號
- **$_**:獲取在些之前執行的命令或指令碼的最後一個引數
以上四個狀態變數,僅$?常用,其他三個瞭解即可。
在日常使場景中,$?主要用法如下所示:
- 1、判斷命令和指令碼是否執行成功
- 2、如指令碼中呼叫exit 數字,則會返回該數字給$?
- 3、如在函式中,則可以通過return 數字將該數字返回給$?
狀態變數示例
1、$?示例:
[[email protected] Test]# ll /etc/profile
-rw-r--r--. 1 root root 1819 4月 11 2018 /etc/profile
[[email protected] Test]# echo $?
0
[[email protected] Test]# ll /etc/profild
ls: 無法訪問/etc/profild: 沒有那個檔案或目錄
[[email protected] Test]# echo $?
2
2、$$示例:
[[email protected] Test]# cat testPID.sh
#!/bin/bash
echo $$ > /tmp/test.pid
sleep 300
[[email protected] Test]# bash testPID.sh & # 將當前指令碼呼叫到後臺執行
[1] 1671
[[email protected] Test]# ps -ef | grep testPID | grep -v grep
root 1671 23706 0 16:37 pts/0 00:00:00 bash testPID.sh # 查詢PID
3、$!示例:
$!功能類似於$$,只不過是獲取上一次執行指令碼的PID
[[email protected] Test]# bash testPID.sh &
[1] 24078
[[email protected] Test]# echo $!
24078 # 列印上一次在後臺執行的程序號
[[email protected] Test]# ps -ef | grep testPID | grep -v grep
root 24078 23706 0 16:42 pts/0 00:00:00 bash testPID.sh
4、$_示例:
[[email protected] Test]# bash para.sh {a..z}
a b c d e f g h i j k l m n o
$0 is: para.sh
$1 is: a
$12 is: l
$# is: 26
$* is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"$*"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
[email protected] is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"[email protected]"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
[[email protected] Test]# echo $_
z # 列印最後一個傳入的引數值
Bash 內建變數
常用的內部命令有echo、eval、exec、export、read、shift、exit。
echo
主要用於列印資訊,其命令格式如下所示:
echo [options] args
常用引數如下所示:
引數選項 | 說明 |
---|---|
-n | 不換行輸出內容 |
-e | 解析轉義字元 |
echo常用轉義字元如下:
轉義字元 | 說明 |
---|---|
\n | 換行 |
\r | 回車 |
\t | Tab |
\b | 退格 |
\v | 縱向製表符 |
eval
當Shell程式執行到eval語句時,將讀入引數args,並將它們組合成一個新的命令而後執行。其命令格式如下所示:
eval args
exec
exec主要用於在不建立新的子程序的情況下,轉而執行指定的命令,當指定命令執行完後,則終止該程序。其命令格式如下所示:
exec args
當使用exec開啟檔案後,read命令每次都會將檔案指標移動到下一行進行讀取,直至結束。因此常用來處理檔案內容。
read
從標準輸入讀取變數或字串等資訊並傳遞給其他變數,其命令格式如下所示
read args
shift
對傳入的位置引數依次向左移動一個位置,並使用位置引數$#減1,直至0為止。其命令格式如下所示:
shift postition args
shift如果不帶引數,則預設左移1位
如傳入的引數為$1 $2 $3,如執行一次shift,則之前的$3變成$2,$2變成$1,$1消失。
exit
常用於退出Shell,在日常使用過程中可使用exit num來自定義返回狀態數。
Bash 內建變數示例
1、echo
[[email protected] Test]# echo "Test";echo "Dao"
Test
Dao
[[email protected] Test]# echo -n "Test";echo "Dao"
TestDao
[[email protected] Test]# echo -e "Test\tName\n Dao"
Test Name
Dao
2、eval
[[email protected] Test]# cat eval.sh
#!/bin/bash
echo "No eval"
echo \$$#
echo "Add eval"
eval echo \$$#
[[email protected] Test]# bash eval.sh a b
No eval
$2 # 未新增evel時,$#為2,則輸出$2
Add eval
b # 新增evel後,則重新對傳入的引數進行解析,則輸出傳入的第2個引數
3、exec
[[email protected] Test]# exec ls
eval.sh para.sh ping.sh testPID.sh testposition.sh
[[email protected] ~]$ # 在執行exec後則終止當前Shell程序,因此從root使用者退出到普通使用者
# 與read一起讀取檔案
[[email protected] ~]# seq 5 > /tmp/rand.log
[[email protected] ~]# cat /tmp/rand.log
1
2
3
4
5
[[email protected] Test]# cat exec.sh
#!/bin/bash
exec < /tmp/rand.log
while read line
do
echo $line
done
echo "Completed"
[[email protected] Test]# bash exec.sh
1
2
3
4
5
Completed
4、read
可以參考公眾號中read命令一文
5、shift
[[email protected] Test]# cat shift.sh
#!/bin/bash
echo $1 $2 $3 $4 $5
until [ -z $1 ]
do
echo [email protected]
shift 1
done
[[email protected] Test]# bash shift.sh {1..5}
1 2 3 4 5
1 2 3 4 5
2 3 4 5
3 4 5
4 5
5
變數擴充套件
變數擴充套件說明
Shell中變數擴充套件說明如下所示:
- ${var}:返回${var}的內容
- ${#var}:返回${var}的字元長度
- ${var:offset}:返回${var}從位置offset之後開始提取字元至結束
- ${var:offset:length}:返回${var}從offset之後,提取長度為length的字元
- ${var#word}:返回從${var}開頭開始刪除最短匹配的word子符串
- ${var##word}:返回從${var}開頭開始刪除最長匹配的word子符串
- ${var%word}:返回從${var}結尾開始刪除最短匹配的word子符串
- ${var%%word}:返回從${var}結尾開始刪除最長匹配的word子符串
- ${var/oldstring/newstring}:使用newstring替換第一個匹配的字元oldstring
- ${var//oldstring/newstring}:使用newstring替換所有匹配的字元oldstring
- ${var:-word}:如果變數var的值為空或未賦值,則將word做為返回值,常用於防止變數為空或未定義而導致的異常
- ${var:=word}:如果變數var的值為空或未賦值,則將word賦值給var並返回其值。
- ${var:?word}:如果變數var的值為空或未賦值,則將word做為標準錯誤輸出,否則則輸出變數的值,常用於捕捉因變數未定義而導致的錯誤並退出程式
- ${var:+word}:如果變數var的值為空或未賦值,則什麼都不做,否則word字元將替換變數的值
其中${var:-word}、${var:=word}、${var:?word}、${var:+word}中的冒號也可以省略,則將變數為空或未賦值修改為未賦值,去掉了為空的檢測, 即運算子僅檢測變數是否未賦值
變數擴充套件示例
[[email protected] init.d]# var="This is test string"
[[email protected] init.d]# echo $var
This is test string
[[email protected] init.d]# echo ${var}
This is test string
[[email protected] init.d]# echo ${#var} # 統計字元長度
19
[[email protected] init.d]# echo ${var:5} # 從第5個位置開始擷取字元
is test string
[[email protected] init.d]# echo ${var:5:2} # 從第5個位置開始擷取2個字元
is
[[email protected] init.d]# echo ${var#This} # 從開頭刪除最短匹配的字元 is
is test string
[[email protected] init.d]# echo ${var##This} # 從開頭刪除最長匹配的字元 is
is test string
[[email protected] init.d]# echo ${var%g} # 從結尾刪除最短匹配的字元 is
This is test strin
[[email protected] init.d]# echo ${var%%g} # 從結尾刪除最長匹配的字元 is
This is test strin
[[email protected] init.d]# echo ${var/is/newis} # 替換第一個匹配的字元
Thnewis is test string
[[email protected] init.d]# echo ${var//is/newis} # 替換所有匹配到的字元
Thnewis newis test string
[[email protected] init.d]# echo $centos # 變數未定義
[[email protected] init.d]# echo ${centos:-UNDEFINE} # 變數為空,返回UNDEFINE
UNDEFINE
[[email protected] init.d]# centos="CentOS"
[[email protected] init.d]# echo ${centos:-UNDEFINE} # 變數已經定義,返回變數本身的值
CentOS
[[email protected] init.d]# unset centos # 取消變數值
[[email protected] init.d]# echo $centos
[[email protected] init.d]# result=${centos:=UNDEFINE}
[[email protected] init.d]# echo $result
UNDEFINE
[[email protected] init.d]# echo $centos # 變數值為空,則將UNDEFINE賦值給centos
UNDEFINE
[[email protected] init.d]# unset centos
[r[email protected] init.d]# echo ${centos:?can not find variable centos}
-bash: centos: can not find variable centos # 變數值為空,輸出自定義錯誤資訊
[[email protected] init.d]# centos="IS DEFINED"
[[email protected] init.d]# echo ${centos:?can not find variable centos}
IS DEFINED #變數值已定義,則輸出變數值
[[email protected] init.d]# unset centos
[[email protected] init.d]# echo ${centos:+do nothing} # 變數值為空,什麼都不操作輸出
[[email protected] init.d]# centos="do"
[[email protected] init.d]# echo ${centos:+do nothing} # 變數已賦值,則輸出自定義的訊息
do nothing
本文同步在微信訂閱號上釋出,如各位小夥伴們喜歡我的文章,也可以關注我的微信訂閱號:woaitest,或掃描下面的二維碼新增關注: