Shell中的特殊位置引數變數全文收錄
一、位置引數變數的作用
一句話概括:我們要從命令列、函式或者指令碼執行等處傳遞引數時,就需要在shell指令碼中使用位置引數變數
二、Shell中的特殊未知引數變數有哪些
1)$0
作用:獲取當前執行的shell指令碼的指令碼名字(如果指令碼中包含了路徑,那獲取的就是指令碼路徑)
2)$n
作用:獲取當前執行的shell指令碼的第n個引數(n=1..9),當n=0時,則就是$0獲取指令碼名,當n≥10,則必須使用{},例如:${10},當n有多個時,則引數之間用空格隔開
3)$#
作用:獲取當前執行的shell指令碼後面接的引數的總個數
4)$
作用:獲取當前執行的shell指令碼後面所有的引數,如果給$加上雙引號,即*"$"時,則表示把所有的引數視為不同的單個**字串,相當於:"$1 $2 $3"5)[email protected]
作用:獲取當前執行的shell指令碼後面所有的引數,如果給[email protected]加上雙引號,即"[email protected]"時,則表示把所有的引數視為不同的獨立字串,相當於:"$1" "$2" "$3",這種方式是把多引數傳遞給其他程式的最佳方式,因為它會保留所有的內嵌在每個引數裡的任何空白
特殊說明:當*"$"和"[email protected]"**都加雙引號時是有區別的,當兩者都不加雙引號時,是完全沒區別的
6)$?
作用:獲取執行上一個指令的執行狀態返回值(0為成功,非0為失敗,⭐️這個變數非常的常用⭐️)
7)$$
作用:獲取當前執行的shell指令碼的程序號(即PID),不太常用,瞭解即可
8)$!
作用:獲取上一個在後臺工作的程序的程序號,不太常用,瞭解即可
9)$_
獲取在此之前執行的命令或指令碼的最後的一個引數,類似於我們使用的快捷鍵“esc+.”,因為是在非互動模式下,所以使用$_,一般常用,瞭解即可
三、分別距離說明9個特殊位置引數變數
1)$0
[[email protected] ~]# vim abc.sh
[[email protected] ~]# cat abc.sh
echo $0
[[email protected] ~]# sh abc.sh
abc.sh
[[email protected] ~]# sh /root/abc.sh
/root/abc.sh
如果想單獨獲取指令碼名或者路徑,則配合下面的小命令:
[[email protected] ~]# basename /root/abc.sh
abc.sh
關於basename的詳細講解,請瀏覽地址:
http://blog.51cto.com/zpf666/2335218
[[email protected] ~]# dirname /root/abc.sh
/root
關於dirname的詳細講解,請瀏覽地址:
http://blog.51cto.com/zpf666/2335223
說明:若不帶路徑執行指令碼,則輸出的結果就是指令碼名;
如果使用全路徑執行指令碼,那麼輸出的結果就是全路徑+指令碼名
2)$n
[[email protected] ~]# vim abc.sh
[[email protected] ~]# cat abc.sh
echo $1
[[email protected] ~]# sh abc.sh dabiaoge
dabiaoge
[[email protected] ~]# vim abc.sh
[[email protected] ~]# cat abc.sh
echo $1 $2
[[email protected] ~]# sh abc.sh dabiaoge dabiaoge2
dabiaoge dabiaoge2
[[email protected] ~]# vim abc.sh
[[email protected] ~]# cat abc.sh
echo $1 $2 $3
[[email protected] ~]# sh abc.sh "dabiaoge dabiaoge2" dabiaoge3 dabiaoge4
dabiaoge dabiaoge2 dabiaoge3 dabiaoge4
說明:⑴引數與引數之間用空格隔開
⑵加引號括起來的引數會作為一個字串看待
[[email protected] ~]# echo \${1..15} > num.sh
[[email protected] ~]# cat num.sh
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[[email protected] ~]# vim num.sh
[[email protected] ~]# cat num.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[[email protected] ~]# sh num.sh {a..z}
a b c d e f g h i a0 a1 a2 a3 a4 a5
為什麼會出現a0 a1 a2 a3 a4 a5,而不是字母呢?這是因為前面提過的,當n≥10,則必須使用{},例如:${10},請看下面:
[[email protected] ~]# vim num.sh
[[email protected] ~]# cat num.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
[[email protected] ~]# sh num.sh {a..z}
a b c d e f g h i j k l m n o
說明:⑴當n≥10,則必須使用{}
⑵生產環境下規範的寫法是"$1" "$2" "$3",就是$n用雙引號括起來
3)$#
[[email protected] ~]# vim abc.sh
[[email protected] ~]# cat abc.sh
echo $#
[[email protected] ~]# sh abc.sh {a..z}
26
條件表示式判斷語句的寫法(例子):
[[email protected] ~]# vim tt1.sh
[[email protected] ~]# cat tt1.sh#!/bin/bash [ $# -ne 2 ] && { //“-ne”是不等於的意思,“-eq”是等於的意思 echo "必須兩個引數" exit 1 } echo dabiaoge_nb
[[email protected] ~]# sh tt1.sh dabiaoge1
必須兩個引數
[[email protected] ~]# sh tt1.sh dabiaoge1 dabiaoge2
dabiaoge_nb
if判斷語句的寫法(例子):
[[email protected] ~]# vim tt2.sh
[[email protected] ~]# cat tt2.sh#!/bin/bash if [ $# -ne 2 ] then echo "用法:/bin/sh $0 引數1 引數2" //注意此處的$0,列印指令碼名 exit 1 fi echo $1 $2
[[email protected] ~]# sh tt2.sh dabiaoge1
用法:/bin/sh tt2.sh 引數1 引數2
[[email protected] ~]# sh tt2.sh dabiaoge1 dabiaoge2
dabiaoge1 dabiaoge2br/>4)**$***和**[email protected]**
舉例說明的材料:
[[email protected] ~]# set -- "I am" big biaoge //“set --”表示清除所有的引數變數,重新設定後面的引數變數
[[email protected] ~]# echo $#
3
[[email protected] ~]# echo $1
I am
[[email protected] ~]# echo $2
big
[[email protected] ~]# echo $3
biaoge
測試①:兩者都不帶雙引號
普通測試:
[[email protected] ~]# echo $
I am big biaoge
[[email protected] ~]# echo [email protected]
I am big biaoge
使用for迴圈測試:
[[email protected] ~]# for i in $;do echo $i;done
I
am
big
biaoge
[root[email protected] ~]# for i in [email protected];do echo $i;done
I
am
big
biaoge
[[email protected] ~]#
說明:兩次測試結果兩者完全一樣,甚至“I am”這第一個引數也給分開了。
測試②:兩者都帶雙引號
普通測試:
[[email protected] ~]# echo "$*"
I am big biaoge
[[email protected] ~]# echo "[email protected]"
I am big biaoge
使用for迴圈測試:[[email protected] ~]# for i in "$*";do echo $i;done I am big biaoge [[email protected] ~]# for i in "[email protected]";do echo $i;done I am big biaoge [[email protected] ~]# for i;do echo $i;done I am big biaoge
說明:當普通測試的時候還是完全沒區別,一旦使用for迴圈測試,就出現了不同之處。*即:在for迴圈+雙引號的情況下,$和[email protected]是不一樣的。
去掉"in 變數列表",相當於有引號的in "[email protected]"。
5)$?
[[email protected] ~]# pwd
/root
[[email protected] ~]# echo $?
0
[[email protected] ~]# ls /dabiaoge
ls: cannot access /dabiaoge: No such file or directory
[[email protected] ~]# echo $?
2
說明:在生產環境下,$?返回值的用法:
①判斷命令、指令碼或函式等程式是否執行成功
②若在指令碼中呼叫執行“exit 數字”,則會返回這個數字給“$?”變數
③如果是在函式裡面,則通過“return 數字”把這個數字以函式返回值的形式傳給“$?”
6)$$**
[[email protected] ~]# vim test_pid.sh
[[email protected] ~]# cat test_pid.sh
echo $$ > /tmp/abc.pid
sleep 300
[[email protected] ~]# ps -ef | grep test_pid | grep -v grep
[[email protected] ~]# sh test_pid.sh &
[1] 13107
[[email protected] ~]# ps -ef | grep test_pid | grep -v grep
root 13107 3977 0 22:01 pts/0 00:00:00 sh test_pid.sh
[[email protected] ~]# cat /tmp/abc.pid
13107
說明:通過ps看到的指令碼的程序號13107與/tmp/abc.pid裡面的數字是一樣的,這就是靠$$傳參過來的值。
一般運用場景:有時執行定時任務指令碼的頻率比較快,並不知道上一個指令碼是否真的執行完畢,但是,業務要求同一時刻只能有一個同樣的指令碼在執行,此時就需要利用$$來獲取上一次執行的指令碼程序號,當程式重新執行時,根據獲取的程序號,清理掉上一次的程序。舉例指令碼如下:
[[email protected] ~]# cat pid.sh#!/bin/bash pidpath=/tmp/ceshi.pid #如果pid檔案存在,則執行then後面的命令 if [ -f "$pidpath" ] then #殺掉與前一個程序號對應的程序 kill $(cat $pidpath) > /dev/null 2&>1 rm -rf $pidpath fi echo $$ > $pidpath sleep 300
[[email protected] ~]# ps -ef | grep pid.sh | grep -v grep
[[email protected] ~]# sh pid.sh &
[1] 13580
[[email protected] ~]# ps -ef | grep pid.sh | grep -v grep
root 13580 3977 0 22:13 pts/0 00:00:00 sh pid.sh
[[email protected] ~]# sh pid.sh &
[2] 13592
[[email protected] ~]# ps -ef | grep pid.sh | grep -v grep
root 13592 3977 0 22:13 pts/0 00:00:00 sh pid.sh
[1]- Terminated sh pid.sh
[[email protected] ~]# sh pid.sh &
[3] 13603
[[email protected] ~]# ps -ef | grep pid.sh | grep -v grep
root 13603 3977 0 22:13 pts/0 00:00:00 sh pid.sh
[2]- Terminated sh pid.sh
7)$!
[[email protected] ~]# ps -ef | grep pid.sh | grep -v grep
[[email protected] ~]# sh pid.sh &
[1] 13806
[[email protected] ~]# echo $!
13806
[[email protected] ~]# ps -ef | grep pid.sh | grep -v grep
root 13806 3977 0 22:18 pts/0 00:00:00 sh pid.sh
說明:$!的功能類似於$$,只不過作用是獲取上一次執行指令碼的pid
8)$_
[[email protected] ~]# systemctl restart nginx.service
[[email protected] ~]# systemctl restart nginx.service
[[email protected] ~]# echo $_
nginx.service
說明:$_就是上一條命令的最後一個引數值。