我是 shell 腳本新手,正在嘗試學習基礎知識。我正在使用終端啟動腳本,例如“./scriptgoeshere.sh Argument1 Argument2”。
我希望腳本列印一些回顯,「Hello World」可能是最好使用的一個,但我只希望它在以下情況下列印出 hello world: 恰好有兩個參數,並且這些參數必須僅由數字組成。例如:
./scriptgoeshere.sh 1523 9643 ./scriptgoeshere.sh 7 96 應該可以,但是; ./scriptgoeshere.sh 594 arg 不應該工作,這是我目前的腳本,但它不起作用,我一整天都在嘗試解決這個問題,但似乎無法解決它,我什至嘗試過if/elif/ else我在繼續之前檢查 if 部分中是否有 2 個輸入,以及它們是否都是 elif 中的數字。
#!/bin/bash
if [ "$#" -eq 2 ] && [ "$@" -eq ^[0-9] ];
then
i=0
while [ $i -lt 3 ]
do
echo "Hello World!"
sleep 5
i=$((i+1))
done
else
echo "Need two arguments and only numbers will be accepted, such as ./scriptgoeshere 153 251"
fi
它會阻止 hello world 循環,直到我輸入 2 個參數,但它們是數字還是文字並不重要,然後我收到錯誤:「./scriptgoeshere.sh: line 2: [: ^[0-9]:預期的整數表達式」。即使我在終端機中寫入 ./scriptgoeshere.sh 123 123 來啟動它,我也會收到該錯誤。我不想透過變數來解決它,因為我想在啟動實際腳本時找出參數。
這讓我很頭痛!
這就是我開始檢查是否剛好有 2 個參數並且它有效的方法,我只是想對其添加一個小修復,以便這 2 個參數必須是數字。我不明白為什麼看起來這麼難。
#!/bin/bash
if [ "$#" -eq 2 ];
then
i=0
while [ $i -lt 3 ]
do
echo "Hello World!"
sleep 1
i=$((i+1))
done
else
echo "Need two argument, only numbers accepted"
fi
編輯:我解決了。我已經工作得非常接近了..我只需要在 if 字串的數字部分添加額外的 [] 。有人知道為什麼它需要寫成 [[ "$@" -eq ^[0-9] ]] 而第一部分可以只寫一個 [] ?
答案1
起初[ "$#" -eq ^[0-9] ]
或[ "$@" -eq ^[0-9] ]
(這個問題在我寫答案時被編輯了......)。從上下文來看,我認為您想測試參數是否是數字。
$#
始終是一個數字,以十進位表示的位置參數的數量。您想要測試兩個位置參數:$1
和$2
。[
是一個命令([ whatever ]
相當於test whatever
)。它可能是內建的 shell,但在語法上它就像ls
或man
。 shell 解析後面的單字(包括]
),就像命令後面的任何單字一樣:shell 擴展它們(例如,$#
變成數字),刪除引號;最終它們成為 的參數[
。這些擴展之一是檔案名稱擴展,其中各種模式與現有檔案名稱相符(檔案名稱擴展、通配符)。如果這些檔案存在,則未加引號的內容^[0-9]
可能會擴展為。^2 ^5
如果沒有符合項目或停用該功能,^[0-9]
則將按字面意思取得[
(作為其參數之一)。它看起來像一個模式,但[
無論如何都不支援模式匹配。-eq
要求前一個和下一個參數都是整數。$#
肯定會擴展為整數。在這種情況下無法^[0-9]
擴展到數字。雙引號
$@
很特殊,儘管被引用,但它可以擴展到多個單字(POSIX 術語中的“字段”)。通常我們引用是為了防止分詞:"$foo"
即使值包含空格等,也會擴展為一個單字。"$@"
像 一樣擴展"$1" "$2" …
,它的雙引號阻止$1
擴展為多個單字(以及單獨的$2
等等)。在這個片段中:[ "$#" -eq 2 ] && [ "$@" -eq ^[0-9] ]
第二個
[
是運行當且僅當第一個成功(這就是&&
工作原理),即當且僅當有兩個位置參數。在這種情況下"$@"
相當於"$1" "$2"
第二個測試變成[ "$1" "$2" -eq ^[0-9] ]
這沒有道理。
[
可能會根據參數的實際值和 的擴展以不同的方式抱怨^[0-9]
,但它仍然是垃圾。
現在關於[[ "$#" = [0-9] ]]
.
注意:此片段位於問題的第一次修訂中。當我撰寫答案時,該問題已被編輯。我決定保留這個片段,因為[[
無論如何最終可能會有用。
- 再次強調:
$#
始終是個數字。 [[
不等於[
.您可以使用的任何理智測試[
都可以重寫[[
(儘管您不應該通過僅替換為來盲目地執行此操作[
)[[
。還有額外的測試[[
可以做,它的功能更強大。雖然[
(andtest
) 是 POSIX 所要求的,但[[
不是。重要的是:
[[
不是像ls
or 這樣的命令[
。它是一個關鍵字,它改變了 shell 解析後面單字的方式。[[
和之間的所有內容]]
都會以不同的方式解析。如果運算符是
=
,則下一個參數是模式。某些字元/語法(例如*
或[0-9]
)在未加引號時會與 先前的參數進行比對=
。這就像檔案名稱擴展,但不針對現有檔案名稱。您的程式碼測試了(擴充)是否$#
恰好是一位數字。整個測試是[[ "$#" -eq 2 ]] && [[ "$#" = [0-9] ]]
foo && bar
bar
當且僅當成功時運行foo
。只有在擴展為 時才[[
測試第二個,因此它必須成功,因為恰好是一位數字。在這種情況下,第二個沒有任何改變。$#
2
2
[[
假設您意識到自己的錯誤並測試了是否$1
為一個數字。
- 如上所述,如果擴展到恰好一位數字,
[[ "$1" = [0-9] ]]
則返回成功。$1
[[ "$1" = [0-9][0-9] ]]
– 正好兩位數。[[ "$1" = [0-9]* ]]
– 以數字開頭的東西。
偵測您需要的任意數量的數字=~
。裡面的這個運算子[[ ]]
有點類似=
,但現在的模式是一個擴充的正規表示式。不過,它不需要將整個字串匹配到運算符的左側,一個子字串就足夠了(因此在您的情況下需要錨點)^
:$
[[ "$1" =~ [0-9] ]]
$1
如果擴展為包含數字的字串,則傳回成功。[[ "$1" =~ [0-9][0-9] ]]
– …包含兩個相鄰的數字。[[ "$1" =~ ^[0-9]$ ]]
– 恰好是一位數字的字串。[[ "$1" =~ ^[0-9]*$ ]]
– 零個或多個數字。[[ "$1" =~ ^[0-9][0-9]*$ ]]
– 一位或多位數字。[[ "$1" =~ ^[0-9]+$ ]]
– 一位或多位數字。
[[ "$1" =~ ^[0-9]+$ ]]
以及[[ "$2" =~ ^[0-9]+$ ]]
您可能想要的測試。為了允許前導-
修改它們,如下所示:[[ "$1" =~ ^-?[0-9]+$ ]]
.整個測試片段可能是
[ "$#" -eq 2 ] && `[[ "$1" =~ ^-?[0-9]+$ ]]` && `[[ "$2" =~ ^-?[0-9]+$ ]]`
內部[[ ]]
變數/參數不能用雙引號引起來,而且它們的擴展值不會進行分詞和通配。所以你可以寫[[ $1 =~ ^-?[0-9]+$ ]]
,而且很安全。這是一個例外;一般來說,你應該用雙引號變數。這裡雙引號不會幹擾任何事情,所以我建議無論如何都要引用以習慣這種良好的一般實踐。
您聲稱您使用 解決了問題[[ "$@" -eq ^[0-9] ]]
。對不起,我不相信你。如果恰好有兩個位置參數並且它們是數字,我看不出這在語法上是正確的,更不用說測試你想要的了。在其他情況下……我仍然沒有找到辦法。
……使用[[ "$@" =~ ^[0-9] ]]
(來自您的評論,與問題不連貫)。這不是一個正確的解決方案。我的測驗顯示"$@"
inside 的[[ ]]
行為就像未加引號的一樣$@
,被視為一個單詞,沒有分詞和通配符。這與常規變數在內部的行為非常相似[[ ]]
,儘管事先對我來說並不明顯,因為我知道"$@"
它不像常規變數。
附註:基於這個原因,我從來不想使用"$@"
inside [[ ]]
。我無法想像當它是正確的時候的場景。
當恰好有兩個位置參數時,您的“解決方案”變為[[ "$1 $2" =~ ^[0-9] ]]
。它在語法上是有效的,它檢查腳本的第一個參數的第一個字元是否是數字。只有這個。運行./scriptgoeshere.sh 0h well
,參數將通過測試。
筆記:
[0-9]
(作為通配模式或正規表示式)取決於您目前的區域設定。它很可能會按您的預期工作,但從技術上講,可能有一個區域設置,其中9
before0
或 where2
is Beyond0-9
。匹配數字的最通用方法是[[:digit:]]
。看這。另一方面,您可能想要使用
$1
and/or$2
與 shell 算術 ($((…))
)[ "$1" -ge 50 ]
等。那你只需要阿拉伯數字。即使[[:digit:]]
將它們包含在您的區域設定中(可能確實如此),它也可能包含其他數字。考慮[0123456789]
;它是明確的並且不依賴語言環境。從and/or
^-?[0-9]+$
的角度來看,並非每個符合的字串都被視為整數(例如,當您這樣做時)。每個工具都有一個可以處理的整數範圍。同樣,如果您向 shell 算術輸入描述超出範圍整數的數字字串,則 shell 算術可能會產生數學上錯誤的結果。[
[[
[ "$1" -eq 0 ]
數學上
1.00
是一個整數。有些工具可能會接受它作為整數,有些可能不會。關於什麼1e100
?