將參數傳遞給腳本

將參數傳遞給腳本

我正在參加 Linux Essentials 課程,並且在學習腳本章節之前一直表現良好。我根本不明白這些概念。想知道是否有人可以將以下內容分解為超簡單的術語,或者為我指出更好的參考來學習它。我目前正在使用 netacad 的課程。


來自教科書(略有格式變更):

除了您設定的變數之外,還有一些特殊變數。您可以將參數傳遞給腳本:

#!/bin/bash
echo "Hello $1"

美元符號後面跟著數字 N 對應於傳遞給腳本的第 N 個參數。如果您呼叫上面的範例,./test.sh輸出將是 Hello Linux。該$0變數包含腳本本身的名稱。

程式運行後,無論是二進位檔案還是腳本,都會傳回一個退出程式碼,該程式碼是 0 到 255 之間的整數$?


我了解如何分配變數以及它們如何與 and 一起工作,$但整個問題與$0-$1我只是不明白。

任何幫助將非常感激。

答案1

書中的描述是錯誤的(或至少遺漏了一些東西)。要讓該腳本列印“Hello Linux”,您可以像這樣運行它:

./test.sh Linux

如果您僅使用 運行它./test.sh,那麼它只會列印“Hello”,因為沒有第一個參數並且$1未定義。另一方面,假設您像這樣運行它:

./test.sh foo bar baz

那麼在腳本中,$0將是“./test.sh”,$1將是“foo”,$2將是“bar”,並將$3是“baz”。

至於$?,請考慮以下腳本片段:

ls nonexistentfile.txt
echo "The exit status of ls was: $?"
echo "The exit status of echo (the first one) was: $?"

運行時會列印如下內容:

ls: nonexistentfile.txt: No such file or directory
The exit status of ls was: 1
The exit status of echo (the first one) was: 0

ls命令無法列出 nonexistentfile.txt(因為它不存在),因此它會列印錯誤訊息來說明這一點,並以非零狀態退出以指示出現問題。第一個echo命令列印退出狀態 ( $?),並且由於它成功完成了該操作,因此它以零狀態退出。當第二個echo命令運行時,它$?從第一個echo命令獲取,因此它列印“0”。

順便說一句,許多指令只使用退出狀態 0(成功)或 1(某種失敗),但有些指令使用不同的失敗狀態來準確指示出了什麼問題。這是摘錄自curl手冊頁

EXIT CODES
       There are a bunch of different  error  codes  and  their  corresponding
       error  messages  that  may appear during bad conditions. At the time of
       this writing, the exit codes are:

       1      Unsupported protocol. This build of curl has no support for this
              protocol.

       2      Failed to initialize.

       3      URL malformed. The syntax was not correct.

       ...

       88     FTP chunk callback reported error

       89     No connection available, the session will be queued

       90     SSL public key does not matched pinned public key

       91     Invalid SSL certificate status.

       92     Stream error in HTTP/2 framing layer.

...因此使用的腳本curl可以檢查$?以找出問題所在,並根據問題做出不同的回應。

答案2

$0是您用來運行腳本的名稱。$1$2等是腳本的位置參數,它們保存執行腳本時傳遞的命令列參數的值。

作為戈登戴維森說,這本書的作者一定是想說跑步./test Linux會印出來Hello Linux。當您這樣做時,./test將進入特殊參數0,並Linux進入第一個位置參數1。該腳本透過在第一個位置參數前面添加美元符號 ( $1) 來擴展第一個位置參數,就像處理變數一樣。如果您改為運行./test Hello Linux for Human Beings,則在腳本中,$1將擴展為Linux$2to for$3toHuman$4to Beings

您可以編寫一個簡單的腳本來嘗試:

#!/bin/bash

echo "\$0 expands to '$0'."
echo "\$1 expands to '$1'."
echo "\$2 expands to '$2'."
echo "\$3 expands to '$3'."

(想寫多少就寫多少。對於高於 的位置參數9,可以使用${ }參數擴展的形式,例如10寫成 來擴展。在使用多個位置參數的腳本中,經常使用${10}特殊參數@

嘗試將其保存在文件中並將該文件標記為可執行文件,您可以透過執行chmod +x simplewheresimple替換為文件名(如果不同)來完成此操作。然後您可以使用./simple./simple foo./simple foo bar等命令運行它。

您會注意到,當傳遞的命令列參數少於三個時,與未傳遞的參數相對應的位置參數將擴展為空字串。這就是當您嘗試擴展未定義的 shell 參數時會發生的情況。此外,您還會注意到,當傳遞更多命令列參數時,不會使用第三個之後的參數。這可能就是您所期望的,因為腳本根本沒有引用它們。

現在嘗試運行./simple *。 shell 擴展*到目前目錄中的所有檔案名稱(以 開頭的檔案名稱除外).,因此其中三個將顯示為前三個位置參數(如果沒有那麼多,則顯示更少)。您可以嘗試使用其他 shell 擴充功能來運行它,例如./simple {5..10}.

您可以將包含空格的命令列參數括在引號中來傳遞它們。例如,嘗試./simple 'foo bar' baz.請注意,$1擴展至foo bar此時,而不僅僅是擴展至foo

因為shell執行各種擴充,傳遞給命令的命令列參數數量並不總是顯而易見。查看每個參數的簡單方法是將命令替換為printf '[%s]\n'。例如:

$ printf '[%s]\n' f*
[fonts]
[fstab]
[fuse.conf]
[fwupd]
$ printf '[%s]\n' {1,3}{a..c}
[1a]
[1b]
[1c]
[3a]
[3b]
[3c]

由於您最近才開始編寫 shell 腳本,Bash 參考手冊可能具有挑戰性,並且您可能不想從頭到尾閱讀它。但我認為即使您認為自己是完全的初學者,這也是一個寶貴的資源。您可能會找到有關以下內容的部分:外殼參數很有用,因為它從您已經知道的內容(shell 變數)開始,然後轉到特殊參數?(人們通常稱之為參數$?,因為這就是擴展它的方式)。對於 Bash 的一般學習,特別是在更入門的級別,我建議這些頁面, 包括Bash指南

答案3

您應該了解的一本好書是 William Shots 的《The Linux Command Line》,由 No Starch Press 出版,可在作者的網站

在每個 shell 腳本中,都有一組編號變量,通常稱為$1$2等。您可以將它們視為名為12等的變量,而要取得它們的值,您可以使用、$1等。變數、、和。您不能指派給這些變數(除非是作為一個群組),但您可以檢查和使用它們的值。例如,將列印腳本的第一個參數。$2my_script./my_script a b c$1$2$3echo "$1"

$0有點不尋常;這是呼叫您正在執行的腳本的名稱。在上面的例子中,它的值為./my_script。同樣,你可以看到它的價值,但不能改變它。

$?是剛剛執行的指令的「退出狀態」。如果命令成功,那麼它的退出狀態將為0,否則它將是一個小的正整數。您可以$?與零進行比較,以查看上一個命令是成功還是失敗。例如,以下兩個命令列將運行grep命令,然後回顯,<1>因為grep失敗並以狀態退出1(表示失敗)。

grep blarg /etc/passwd
echo "<$?>"

退出狀態有助於編寫簡單的腳本,例如:

#!/bin/bash
# grep_pw: grep for a pattern in /etc/passwd
grep "$1" /etc/passwd
if [[ $? = 0 ]] ;then
  echo "Found it"
  exit 0
else
  echo "Unable to find the pattern '$1' in /etc/passwd"
  exit 1
fi

將該文字放入名為 的文件中grep_pw,將其變更為可執行文件chmod 700 grep_pw,然後像./grep_pw nologin查找/etc/passwd包含該字串的行一樣呼叫它nologin

當我第一次了解 shell 時,我發現以下腳本對於理解 shell 如何解析命令列以及因此將哪些命令列參數傳遞給腳本非常有用。

#!/bin/bash
# echoargs: print all the arguments
counter=1
for a in "$@" ;do
   echo "arg $counter=<$a>"
   let counter=counter+1
done

將這些內容放入名為 的文件中echoargs,將其變更為可執行文件chmod 700 echoargs,並像這樣呼叫它:./echoargs a "b c" d

相關內容