
我正在閱讀 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
, ]
,這[
將被理解為x
與x
和x
進行比較x
並傳回 true。
如果$1
是"* *"
,那麼 shell 會將目前目錄中名稱以( 的 glob 擴充功能)[
開頭的檔案清單傳遞給指令,然後是非隱藏檔案清單( 擴充)...這不太可能能夠從中找出任何意義。唯一可以做任何明智的事情的情況是如果不包含通配符或空白字元。x
x*
*
[
$1
現在,您有時會發現如下程式碼:
[ "x$1" = x ]
用於測試是否$1
為空或未設定。
測試空或未設定變數的正常方法是:
[ -z "$1" ]
但是,對於某些(非 POSIX)實作中的某些$1
值(例如Solaris 10 及之前的 Bourne shell 中的內建值)或某些舊版本(最高 0.5.4)或某些BSD 的某些值,該方法會失敗。=
[
/bin/sh
dash
sh
這是因為[
看到[
、-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"