2017年12月28日 星期四

Bash Shell | 什麼是特殊參數 Special Parameters

Bash 提供了一些好用的特殊參數 (Special Parameters),其中很常用到的如:$#, $?, $0, $$,建議要記起來。

1. $*
此參數會被擴展成位置參數 (Positional Parameters),從 $1 開始,當參數沒有被雙引號 (Double Quote) 包起來時,每個位置參數都被當成獨立的字,如果參數被雙引號包起來時,則全部的位置參數會被當成一個字看待,且每一個位置參數之間都用變數 IFS 的第一個字元來做分隔,如果 IFS 是 unset 則用 space 做分隔,如果 IFS 是 null 則位置參數之間沒有字元分隔。

範例:

執行 special_parameter.sh 並傳入四個參數 red orange yellow green 如下

./special_parameter.sh red orange yellow green

#!/bin/sh

echo "\$*"
for i in $*
do
        echo $i
done
echo ""

echo "\"\$*\" and \$IFS = space tab newline"
for i in "$*"
do
        echo $i
done
echo ""

unset IFS
echo "\"\$*\" and unset \$IFS"
for i in "$*"
do
        echo $i
done
echo ""

IFS=
echo "\"\$*\" and \$IFS = null"
for i in "$*"
do
        echo $i
done

echo ""

結果:

$*
red
orange
yellow
green

"$*" and $IFS = space tab newline
red orange yellow green

"$*" and unset $IFS
red orange yellow green

"$*" and $IFS = null
redorangeyellowgreen

2. $@
此參數跟 $* 有像,會被擴展成位置參數 (Positional Parameters),從 $1 開始,但是不管是否參數有沒有被雙引號 (Double Quote) 包起來,每個位置參數都被當成獨立的字。

範例:

執行 special_parameter.sh 並傳入四個參數 red orange yellow green 如下

./special_parameter.sh red orange yellow green

#!/bin/sh

echo "\"\$@\""
for i in "$@"
do
        echo $i
done
echo ""

echo "\$@"
for i in $@
do
        echo $i

done

結果:

"$@"
red
orange
yellow
green

$@
red
orange
yellow
green

3. $#
此參數會被擴展成位置參數 (Positional Parameters)的數量,以十進制顯示。

範例:

執行 special_parameter.sh 並傳入四個參數 red orange yellow green 如下

./special_parameter.sh red orange yellow green

#!/bin/sh

echo \$# = $#

結果:

$# = 4

4. $?
此參數存放最後一個執行之前景(foreground)指令的離開狀態 (Exit Status)

範例:

#!/bin/sh

echo 123 > file1
cmp file1 file1
echo \$? = $?

echo 456 > file2
cmp file2 file2
echo \$? = $?

結果:


$? = 0

file1 file2 differ: byte 1, line 1

$? = 1


5. $-
此參數會被擴展成目前設定為 on 之 option flags 的代表字元,透過 set 指令可以看到 option flags 的設定為何。

範例:

#!/bin/sh

set -o
echo ""
echo \$- = $-

結果:

allexport      off
braceexpand    on
emacs          off
errexit        off
errtrace        off
functrace      off
hashall        on
histexpand      off
history        off
ignoreeof      off
interactive-comments on
keyword        off
monitor        off
noclobber      off
noexec          off
noglob          off
nolog          off
notify          off
nounset        off
onecmd          off
physical        off
pipefail        off
posix          on
privileged      off
verbose        off
vi              off
xtrace          off

$- = hB

說明:

上面為 on 的 option flags 有四個如下
braceexpand
hashall
interactive-comments
posix

用 man set 可以查到

braceexpand Same as -B.
hashall Same as -h.
因此 $- = hB

但是 interactive-comments 與 posix 查不到對應的代表字元。

6. $$
此參數會被擴展成 shell 的 process ID。

範例:

#!/bin/sh

echo Enter $0

echo \$$ = $$

cat /proc/$$/cmdline
echo ""
cat /proc/$$/stat

echo \$_ = $_
echo Leave $0

結果:

Enter ./special_parameter2.sh
$$ = 13735
/bin/sh./special_parameter2.sh
13735 (special_paramet) S 3779 13735 3779 34816 13735 4202496 394 185 0 0 0 0 0 0 20 0 1 0 9952610 5222400 274 4294967295 134508544 135363948 3219852928 3219851956 12153878 0 65536 4 65538 3225663865 0 0 17 0 0 0 0 0 0
$_ = /proc/13735/stat

Leave ./special_parameter2.sh

7. $!
此參數會被擴展成最近一個在背景執行之 process 的 process ID (PID)

範例:

#!/bin/sh

sleep 3 &

echo \$$ = $$
echo \$! = $!

cat /proc/$$/stat

cat /proc/$!/stat

結果:

$$ = 18886
$! = 18887
18886 (bgpid.sh) S 3779 18886 3779 34816 18886 4202496 390 0 0 0 0 1 0 0 20 0 1 0 15692640 5222400 272 4294967295 134508544 135363948 3215265520 3215264548 7701526 0 65536 4 65538 3225663865 0 0 17 0 0 0 0 0 0
18887 (sleep) S 18886 18886 3779 34816 18886 4202496 213 0 0 0 0 0 0 0 20 0 1 0 15692642 4161536 109 4294967295 134512640 134533792 3217654416 3217654040 1864726 0 0 6 0 3225751263 0 0 17 0 0 0 0 0 0

說明:
1. $$ 是 bgpid.sh 的 PID 18886,$! 是在背景執行的 sleep 3 & 的 
   PID 18887
2. 從 /proc/$!/stat 的結果可以看出,18887 是 sleep 且 parent 是 18886

8. $0
此參數會被擴展成 script 的名字,參考上面 $$ 的範例

9. $_
此參數會被擴展成前一個命令的最後一個參數,參考上面 $$ 的範例。

沒有留言:

張貼留言