bash 腳本

bash 腳本

我正在閱讀 bash 腳本,我不明白那裡發生了什麼。

#!/bin/sh
[ x$1 = x ] 

第二行發生了什麼,什麼[ x$1 = x ] 意思?

答案1

它檢查它$1是否為空,儘管它應該被引用(與 相同[ -z "$1" ])。一些非常古老的 shell 無法正確處理空字串,因此可移植腳本的編寫者採用了這種檢查方式。幾十年來,這已經沒有必要了,但人們仍然這樣做,因為人們仍然這樣做。

答案2

方括號表示測試,所以[ x$1 = x]沒有if或類似的東西是沒有意義的,儘管語法上沒問題。

x$1如果擴展為,則計算結果為 true ,x否則為 false ,但由於它未加引號,如果$1是(例如)“hey x”,shell 將看到x = x,因此這種構造仍然不安全。

檢查的目的x = x是確定變數是否為空。更常見的方法是僅使用引號:

if [ "$1" = "" ]; then

Bash 測試操作符-z-n可以使用,但它們對於其他類型的 shell 的可移植性較差。1

使用引號或 的原因x$1是為了使左側不會擴展為空,這將是語法錯誤:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. 實際上,test可以是獨立的實用程序,但大多數 shell 將其實現為內建的;檢查which test和之間的差異type test。在 GNU/Linux 上man test聲稱引用了內建函數,但如果您呼叫 (eg) /usr/bin/test,則該實用程式似乎實現了手冊頁中記錄的功能,包括-z-n

答案3

[ x$1 = x ]

僅在zsh.這會將x與腳本的第一個參數的串聯與 進行比較x。因此,如果為空或未提供,則[命令將傳回 true 。$1

[ $1 = "" ]

不起作用,因為zsh當列表上下文中未引用空變數時,它會擴展為根本沒有參數而不是空參數,因此如果$1未設定或為空,則[命令將僅接收作為參數[, =,空字串這是]無法理解的。[ -z "$1" ][ "$1" = "" ]像在 POSIX shell 中那樣也可以。

在 Bourne-like/POSIX shell 中,[ x$1 = x ]沒有意義。這是 split+glob 運算子以某種方式應用於x腳本的第一個參數的串聯,希望結果 和=x]組成[命令的有效測試表達式。

例如,如果腳本傳遞一個" = x -o x ="參數,[則將接收這些參數:[, x, =, x, -o, x, =, x, ],這[將被理解為xxx進行比較x並傳回 true。

如果$1"* *",那麼 shell 會將目前目錄中名稱以( 的 glob 擴充功能)[開頭的檔案清單傳遞給指令,然後是非隱藏檔案清單( 擴充)...這不太可能能夠從中找出任何意義。唯一可以做任何明智的事情的情況是如果不包含通配符或空白字元。xx**[$1

現在,您有時會發現如下程式碼:

[ "x$1" = x ]

用於測試是否$1為空或未設定。

測試空或未設定變數的正常方法是:

[ -z "$1" ]

但是,對於某些(非 POSIX)實作中的某些$1值(例如Solaris 10 及之前的 Bourne shell 中的內建值)或某些舊版本(最高 0.5.4)或某些BSD 的某些值,該方法會失敗。=[/bin/shdashsh

這是因為[看到[-z=]抱怨=二元運算子缺少參數,而不是將其理解為-z應用於=字串的一元運算子。

同樣,if is or[ "$1" = "" ]的某些實作也會失敗。[$1!(

在這些 shell/[實作中:

[ "x$1" = x ]

無論 的值如何,始終是有效的測試$1,因此:

[ "" = "$1" ]

和:

[ -z "${1:+x}" ]

case $1 in "") ...; esac

當然,如果您想檢查是否未提供任何參數,您可以這樣做:

[ "$#" -eq 0 ]

也就是說,您檢查傳遞給腳本的參數數量。

請注意,如今,[ -z "$var" ]是由 POSIX 明確指定的,並且在一致性實現中不會失敗[(並且bash'[已經存在了幾十年)。所以你應該能夠在 POSIX sh 或bash腳本中依賴它。

答案4

[ x$1 = x ]$1如果unset/null/empty 則為true 。
試試:
TEST= ;[ x$TEST = x] && echo "TEST is unset"

TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"

相關內容