亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Shell 參數

1. Shell 參數概述

在 Shell 腳本編寫中,我們為了使得程序靈活和無狀態,有些變量我們不便于在腳本中寫死,需要運用外部參數傳遞進去,每次傳遞的東西不一樣,得到的結果也不盡相同,參數是與變量相輔相成的,將參數傳遞進 Shell 腳本中,也就成了變量,參數的使用使得我們的腳本更加的靈活和可擴展,同樣也更易維護。

1.1 Shell 參數是什么

Shell 參數是我們在腳本文件外部傳入的一系列參數,或是在 Shell 腳本中給函數傳遞的參數,其實質也就是上一節我們學習的變量,其與變量相輔相成,共同組成 Shell 腳本的一部分。

1.2 為什么要用參數

我們在變量一節知道了為什么利用變量,在此原因與變量類似,參數的使用使得我們的 Shell 腳本更加靈活,不需要在腳本中寫死一些名稱,根據用戶的輸出完成特定的功能,例如編寫腳本計算 100 內數字的和,但是如果我們想計算 1000 呢?100000 呢?每次都需要修改腳本么,我們可以利用參數傳遞進計算腳本中,這樣需要計算多少就由我們自己控制,這樣的腳本也更加靈活,參數賦予腳本更強大的功能。

2. Shell 參數分類

我們知道了 Shell 中參數是什么,來看一下 Shell 腳本中參數的分類。

2.1 位置參數

位置參數顧名思義,就是傳遞給腳本參數的位置,例如給一個腳本傳遞一個參數,我們可以在 Shell 腳本內部獲取傳入的位置參數,獲取參數的格式為:$nn 代表一個數字。例如傳遞給腳本的第一個參數就為 $1,第 2 個參數就為 $2, 以此類推……,其中 $0 為該腳本的名稱。

在我們講解變量的時候,變量的一條規范就是名字不能以數字開頭,在此就是為了避免與 Shell 的位置參數相同引發異常。

例如:

[root@master Shell_args]# cat args1.sh 
#!/bin/bash

echo "第一個參數為: $1"
echo "第二個參數為: $2"
echo "腳本名稱為: $0"

[root@master Shell_args]# bash args1.sh python go
第一個參數為: python
第二個參數為: go
腳本名稱為: args1.sh

我們可以看到傳遞給 args1.sh 腳本兩個位置參數,第一個為 python, 第二個為 go, 腳本名稱為 args1.sh

2.2 特殊參數

在 Shell 中也存在特殊含義的參數如下表:

變量 含義
$# 傳遞給腳本或函數的參數個數總和
$* 傳遞給腳本或函數的所有參數,當被雙引號 " " 包含時,所有的位置參數被看做一個字符串
$@ 傳遞給腳本或函數的所有參數,當被雙引號 " " 包含時,每個位置參數被看做獨立的字符串
$? 上個命令的退出狀態,或函數的返回值,0 為執行成功,非 0 則為執行失敗
$$ 當前 Shell 進程 ID。對于 Shell 腳本,就是這些腳本所在的進程 ID。

示例:

[root@master Shell_args]# cat args2.sh                 
#!/bin/bash

echo "第一個參數為: $1"
echo "第二個參數為: $2"
echo "腳本名稱為: $0"
echo "腳本接受參數總數為: $#"

curl -I baidu.com
echo "運行命令的狀態為:$?"

echo "腳本的ID為:$$"

echo "\$*的結果為:$*"
echo "\$@的結果為:$@"

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

for j in "$@";
do 
        echo $j
done

# 運行腳本來進行測試
[root@master Shell_args]# bash args2.sh go python Shell
第一個參數為: go
第二個參數為: python
腳本名稱為: args2.sh
腳本接收參數總數為: 3
HTTP/1.1 200 OK
Date: Sun, 08 Mar 2020 07:32:22 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-47cf7e6ee8400"
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Mon, 09 Mar 2020 07:32:22 GMT
Connection: Keep-Alive
Content-Type: text/html

運行命令的狀態為:0
腳本的ID為:23333
$*的結果為:go python Shell
$@的結果為:go python Shell
go python Shell
go
python
Shell

我們能夠通過上述例子看出,運行 curl -I baidu.com 的輸出為 0,即為命令運行正常,獲取到了正常的返回值;

$@$* 看上去很像,都是傳遞給腳本或函數的所有參數;

$* 當被雙引號 " " 包含時,所有的位置參數被看做一個字符串,我們用 for 循環遍歷的時候可以看到輸出為一行;

$@當被雙引號 " " 包含時,每個位置參數被看做獨立的字符串,我們用 for 循環遍歷的時候可以看到為每個字符串輸出為單獨的一行。

3. Shell 參數的使用

3.1 腳本傳遞

腳本傳遞參數,就是在運行腳本的時候通過位置參數傳遞進腳本內,每個參數利用一個空格來進行分割,如果傳遞的參數本身就有空格,則可以利用 "" 來引起來,作為一個整體傳遞,在腳本內通過 $n 來獲取。

[root@master Shell_args]# cat args1.sh 
#!/bin/bash

echo "第一個參數為: $1"
echo "第二個參數為: $2"
echo "腳本名稱為: $0"

[root@master Shell_args]# bash args1.sh go "python Shell java"
第一個參數為: go
第二個參數為: python Shell java
腳本名稱為: args1.sh

例如我們第二個參數為一個帶有空格的多個字符串,我們可以用雙引號引起來作為一個位置參數進行傳入。

3.2 函數傳遞

顧名思義,參數傳遞就是在函數外部進行參數的傳入,由于函數部分在后續有專門章節詳解,在此我們就以一個簡單的示例進行說明。函數傳遞與腳本傳遞非常類似,只是在調用函數的時候進行傳遞位置參數即可,例如:

[root@master Shell_args]# cat args_fun.sh 
#!/bin/bash
# 函數定義
function show_args() {
        echo "第一個參數為: $1"
        echo "第二個參數為: $2"
        echo "腳本名稱為: $0"
}

# 函數調用
show_args go Shell
[root@master Shell_args]# bash args_fun.sh 
第一個參數為: go
第二個參數為: Shell
腳本名稱為: args_fun.sh

在示例中,我們可以看到沒有通過在腳本外部進行參數傳遞,而是在調用 show_args 函數的時候傳入來兩個參數。

4. 實例

4.1 需求

我們來做一個內網批量掃描可用 IP 腳本,用來判斷某一個網段中的網絡可達性。

4.2 思路

可以利用 ping 命令來檢測可以 ping 通的 IP,將返回正常的內容記錄在 success.log 中,失敗的內容記錄在 fail.log 中。

傳遞兩個參數,第一個參數為網絡前綴,例如 192.168.0.,然后在腳本內部循環 1-255 來檢測。

第二個參數為 ping 包的個數,如果包太多,時間花費太長,太短有可能造成誤判,在此我們建議使用 2 個包來判斷。

4.3 實現

[root@master Shell_args]# cat ping.sh 
#!/bin/bash
# Description: net check scripts
# Auth: kaliarch
# Email: [email protected]
# function: net check
# Date: 2020-03-08 14:00
# Version: 1.0

# 日志目錄
LOG_DIR="/tmp/netlog/"
# 如果日志目錄不存在則創建
[ ! -d ${LOG_DIR} ] && mkdir -p ${LOG_DIR}
# 定義成功與失敗日志文件
SUCCESS_LOGFILE="success.log"
FAIL_LOGFILE="fail.log"

# 網絡前綴
NET_PREFIX=$1
# 檢測包數量
PACKAGE_NUM=$2


for num in `seq 1 255`;
do
        # 進行ping檢測
        echo "check ${NET_PREFIX}${num}..."
        ping -c ${PACKAGE_NUM} ${NET_PREFIX}${num} &>/dev/null
        # 如果返回正常則記錄可以ping通的ip到successlog中
        [ $? -eq 0 ] && echo ${NET_PREFIX}${num} >> ${LOG_DIR}${SUCCESS_LOGFILE} || echo ${NET_PREFIX}${num} >> ${LOG_DIR}${FAIL_LOGFILE}
done


# 測試
[root@master Shell_args]# bash ping.sh 172.16.60. 2
check 172.16.60.1...
check 172.16.60.2...
check 172.16.60.3...
check 172.16.60.4...
check 172.16.60.5...
check 172.16.60.6...

當腳本運行完成后,可以在 /tmp/netlog/ 目錄下查看成功與失敗的 IP 信息。

5. 注意事項

  • 需要在實戰中理解參數的特殊用處,在編寫腳本中盡可能多用參數,使得腳本無狀態;
  • 需要理解 $@$* 兩個的不同之處,在使用循環的時候需要格外注意;
  • 在利用位置參數傳入腳本的時候,最好利用變量去接收傳遞的外部位置參數,便于我們在腳本內識別參數的具體含義。

6. 小結

參數與變量是相輔相成的,將變量傳遞進腳本或函數就為參數,腳本與變量配合使得我們的腳本更加通用,適應更廣的需求。需要牢記特殊參數的形式,在后期的 Shell 編程中,這些參數是腳本編程的基石,只有基礎牢靠,后續的使用才會得心應手,對上述的例子可以舉一反三,例如探測某一個 IP 的所有端口是否開放等,在實際應用場景中熟悉各種參數的用法。