Shell 腳本中常用的內(nèi)置變量 你知道嗎?
本文轉(zhuǎn)載自微信公眾號(hào)「Linux開發(fā)那些事兒」,作者LinuxThings。轉(zhuǎn)載本文請(qǐng)聯(lián)系Linux開發(fā)那些事兒公眾號(hào)。
在 Bash 解釋器中,內(nèi)置了許多變量,這些變量的功能是解釋器自帶的,我們?cè)诰帉憇hell腳本時(shí)如果能靈活的使用它們,對(duì)腳本的編寫效率以及差錯(cuò)大有幫助, 下面一一介紹這些變量
$FUNCNAME、$LINENO、$PWD
FUNCNAME和LINENO 變量經(jīng)常用于腳本的調(diào)試
FUNCNAME 表示當(dāng)前函數(shù)的名字,作用范圍僅限函數(shù)中使用,在函數(shù)外無值
LINENO 表示當(dāng)前所在腳本中變量出現(xiàn)在的行號(hào)
PWD 表示當(dāng)前目錄, 對(duì)應(yīng)于 pwd命令
現(xiàn)有個(gè)腳本 a.sh 內(nèi)容如下
- 1 #!/bin/bash
- 2
- 3
- 4 testa()
- 5 {
- 6 echo 'func='$FUNCNAME,$LINENO
- 7 }
- 8
- 9
- 10 testa
- 11
- 12 echo 'lineno:'$LINENO
- 13 echo 'xx:'$FUNCNAME
- 14 echo 'curpath:'$PWD
執(zhí)行 ./a.sh 命令, 輸出如下
- [tt@ecs-centos-7 ~]$ ./a.sh
- func=testa,6
- lineno:12
- xx:
- curpath:/home/tt
在 testa 函數(shù)中 FUNCNAME 變量值是 testa,也即函數(shù)名字,在函數(shù)外部無值
LINENO 變量無論是在函數(shù)中還是函數(shù)外,都表示當(dāng)前所在的行號(hào)
$$、$PPID
這兩個(gè)變量依次表示當(dāng)前進(jìn)程ID和父進(jìn)程ID
現(xiàn)有 a.sh 腳本,內(nèi)容如下
sleep 20 睡眠語句是為了讓執(zhí)行腳本進(jìn)程暫緩?fù)顺?,在另一個(gè)終端中驗(yàn)證輸出的結(jié)果
- #!/bin/bash
- #set -u
- echo 'cur pid:'$$
- echo 'parent pid:'$PPID
- sleep 20
在當(dāng)前終端執(zhí)行 ./a.sh,結(jié)果如下
- [tt@ecs-centos-7 ~]$ ./a.sh
- cur pid:13095
- parent pid:12982
在執(zhí)行a.sh的腳本進(jìn)程退出之前,打開另一個(gè)終端,執(zhí)行 ps -o pid,ppid,time,cmd -p 12982,13095 命令,結(jié)果如下
- [tt@ecs-centos-7 ~]$ ps -o pid,ppid,time,cmd -p 12982,13095
- PID PPID TIME CMD
- 12982 12981 00:00:00 -bash
- 13095 12982 00:00:00 /bin/bash ./a.sh
從上面的結(jié)果可以看出, 執(zhí)行 ./a.sh 命令之后,$$ 變量表示的是 執(zhí)行a.sh腳本的進(jìn)程ID 13095 ,而 12982 是它的父進(jìn)程ID,也即是 PPID變量的值,它是當(dāng)前bash的實(shí)例
$0,$1,$2...$n、$#
$# 表示從命令行傳入腳本的參數(shù)數(shù)量
$0,$1,$2...$n 是從命令行傳遞到腳本的參數(shù) $0 是腳本本身的名字 $1 是第一個(gè)參數(shù) $2 是第二個(gè)參數(shù),依此類推 $n 是第n個(gè)參數(shù)
第十個(gè)參數(shù)及以后的參數(shù)必須要用大括號(hào)括起來,例如: ${10}、${11}、${12} 依次表示第十個(gè)變量、第十一個(gè)變量、第十二個(gè)變量
$*、$@
都表示位置參數(shù),不過它們之間也有些不同點(diǎn)
使用 $* 時(shí),如果加上雙引號(hào),即 "$* " 的形式,那所有位置的參數(shù)會(huì)被當(dāng)作一個(gè)單詞來處理,如果不包含雙引號(hào),即 $* 的形式,則每個(gè)位置的參數(shù)都被當(dāng)作一個(gè)獨(dú)立的單詞來處理
而對(duì)于 $@,無論是否加上雙引號(hào),每個(gè)位置的參數(shù)都被當(dāng)作一個(gè)獨(dú)立的單詞來處理
現(xiàn)有c.sh, 內(nèi)容如下
- #!/bin/bash
- cnt=1
- echo 'test 1111'
- for var in "$*"
- do
- echo "arg$cnt="$var
- let "cnt+=1"
- done
- echo
- cnt=1
- echo 'test 2222'
- for var in $*
- do
- echo "arg$cnt="$var
- let "cnt+=1"
- done
- echo
- cnt=1
- echo 'test 3333'
- for var in "$@"
- do
- echo "arg$cnt="$var
- let "cnt+=1"
- done
- echo
- cnt=1
- echo "test 4444"
- for var in $@
- do
- echo "arg$cnt="$var
- let "cnt+=1"
- done
執(zhí)行 ./c.sh 1 2 3,結(jié)果如下
- [root@ecs-centos-7 ~]# ./c.sh 1 2 3
- test 1111
- arg1=1 2 3
- test 2222
- arg1=1
- arg2=2
- arg3=3
- test 3333
- arg1=1
- arg2=2
- arg3=3
- test 4444
- arg1=1
- arg2=2
- arg3=3
從上面的結(jié)果可以看出,對(duì)于 $* 來說,加了雙引號(hào)之后所有位置參數(shù)就會(huì)被視為一個(gè)單詞
對(duì)于 $@ 來說,是否加雙引號(hào),結(jié)果都是一樣的
所以,僅在使用雙引號(hào)時(shí),$*和 $@ 才會(huì)有差異
$?
命令、函數(shù)或者腳本的退出狀態(tài),在判斷命令的執(zhí)行結(jié)果或者函數(shù)的調(diào)用結(jié)果時(shí)很有用處
現(xiàn)有 e.sh 和 f.sh 測試腳本
e.sh 腳本
- #!/bin/bash
- test_func()
- {
- if [[ $1 -eq 10 ]]; then
- return 5
- fi
- return 6
- }
- if [ $# -ge 1 ]; then
- name="$1"
- shift 1
- $name "$@"
- fi
f.sh 腳本
- #!/bin/bash
- sh e.sh test_func 3
- echo 'exit code1:'$?
- sh e.sh test_func 10
- echo 'exit code2:'$?
- test -f $PWD/xx.txt
- echo 'exit code3:'$?
- test -f $PWD/e.sh
- echo 'exit code4:'$?
執(zhí)行 ./f.sh 命令,結(jié)果如下
- [root@ecs-centos-7 ~]# ./f.sh
- exit code1:6
- exit code2:5
- exit code3:1
- exit code4:0
腳本 e.sh 中 test_func 函數(shù)功能是:當(dāng)參數(shù)等于10時(shí),退出狀態(tài)為 5,否則為 6
sh e.sh test_func 3 命令會(huì)調(diào)用 e.sh 腳本中的 test_func函數(shù),傳入?yún)?shù)是 3,所以退出狀態(tài)為 6,同理可知, sh e.sh test_func 10 命令的退出狀態(tài)是 5
在Linux中,命令執(zhí)行成功,退出狀態(tài)為 0 ,失敗則為非 0
test -f $PWD/xx.txt 命令是檢查當(dāng)前目錄是否存在 xx.txt 文件,因當(dāng)前目錄并不存在 xx.txt,所以命令執(zhí)行失敗,退出狀態(tài)為非 0
由于e.sh 存在于當(dāng)前目錄下,所以 test -f $PWD/e.sh 命令執(zhí)行成功,退出狀態(tài)為 0
$IFS
此變量用于 Bash 識(shí)別字符串或單詞邊界,默認(rèn)值是空格,腳本中根據(jù)需要可以修改此變量的值
現(xiàn)有 b.sh腳本,內(nèi)容如下
- #!/bin/bash
- va="a:b:c"
- vb="x-y-z"
- vc="e,f,g"
- IFS=":"
- echo 'va:'$va
- echo 'vb:'$vb
- echo 'vc:'$vc
- echo
- IFS="-"
- echo 'va:'$va
- echo 'vb:'$vb
- echo 'vc:'$vc
- echo
- IFS=","
- echo 'va:'$va
- echo 'vb:'$vb
- echo 'vc:'$vc
執(zhí)行 ./b.sh 結(jié)果如下
- [tt@ecs-centos-7 ~]$ ./b.sh
- va:a b c
- vb:x-y-z
- vc:e,f,g
- va:a:b:c
- vb:x y z
- vc:e,f,g
- va:a:b:c
- vb:x-y-z
- vc:e f g
從結(jié)果可以看出,當(dāng) $IFS 為 : 時(shí),字符串 "a:b:c"被解析成 a b c
當(dāng) $IFS 為 - 時(shí),字符串 "x-y-z"被解析成 x y z
當(dāng) $IFS 為 , 時(shí),字符串 "e,f,g"被解析成 e f g
$HOME、$USER、$UID、$GROUPS
- HOME: 用戶home目錄
- USER: 當(dāng)前用戶名
- UID: 當(dāng)前用戶ID
- GROUPS: 當(dāng)前用戶組ID
- [tt@ecs-centos-7 ~]$ echo $HOME
- /home/tt
- [tt@ecs-centos-7 ~]$ echo $USER
- tt
- [tt@ecs-centos-7 ~]$ echo $UID
- 1003
- [tt@ecs-centos-7 ~]$ echo $GROUPS
- 1003
$HOSTTYPE、$MACTYPE、$OSTYPE
這些變量都表示系統(tǒng)硬件
- [tt@ecs-centos-7 ~]$ echo $HOSTTYPE
- x86_64
- [tt@ecs-centos-7 ~]$ echo $MACHTYPE
- x86_64-redhat-linux-gnu
- [tt@ecs-centos-7 ~]$ echo $OSTYPE
- linux-gnu
小結(jié)
本文介紹了一些常用的 Bash 內(nèi)置變量,對(duì)于一些生僻或者平常很少用到的變量可以自行查閱相關(guān)資料