當我使用空字元串作為參數時,“read”shell 命令的“-d”選項有什麼作用?
當我閱讀這個答案時,作者使用這個命令將heredoc的結果放到一個變數中:
read -r -d '' VAR <<'EOF' abc'asdf" $(dont-execute-this) foo"bar"'' EOF
我對這個
-d
選項有點困惑。從read
命令的幫助文本中:-d delim continue until the first character of DELIM is read, rather than newline
因此,如果我將一個空字元串傳遞給
-d
,則意味著讀取到第一個空字元串。這是什麼意思?作者在答案下發表評論,這-d ''
意味著使用 NUL 字元串作為分隔符。這是真的嗎(空字元串表示 NUL 字元串)?為什麼不使用之類的東西-d '\0'
?-d '\x0'
大多數情況下,它的意思是它所說的,例如:
$ 閱讀 -d 。變種;迴聲; 迴聲“讀取:'$var'” 富。 閱讀:“富”
閱讀立即在 處結束
.
,我沒有在此處輸入。但是
read -d ''
有點特殊,線上參考手冊說:-d delim delim
的第一個字元用於終止輸入行,而不是換行符。如果 delim 是空字元串,read 將在讀取 NUL 字元時終止一行。
\0
表示 中的 NUL 字節printf
,所以我們有例如:$ printf 'foo\0bar\0' | while read -d '' var; do echo "read: '$var'"; done read: 'foo' read: 'bar'
在您的範例中,
read -d ''
用於防止換行符成為分隔符,允許它一次性讀取多行字元串,而不是一次讀取一行。我認為一些舊版本的文件沒有明確提到
-d ''
. 這種行為最初可能是與 Bash 如何以 C 方式儲存字元串以及尾隨 NUL 字節的意外巧合。字元串foo
儲存為foo\0
,空字元串儲存為 just\0
。因此,如果實現不小心防範它並且只選擇記憶體中的第一個字節,它將看到\0
NUL 作為空字元串的第一個字節。更仔細地重新閱讀這個問題,你提到:
作者在答案下發表評論,這
-d ''
意味著使用NUL 字元串作為分隔符。這並不完全正確。空字元串(在 POSIX 用語中)表示長度為零的空字元串,即不包含任何內容的字元串。這與NUL 字節不同,後者是二進制值為零(*)的單個字節。如果你使用空字元串作為分隔符,你會發現它幾乎無處不在,在每個可能的位置。我認為這在 shell 中是不可能的,但例如在 Perl 中,可以像這樣拆分字元串,例如:
$ perl -le 'print join ":", split "", "foobar";' f:o:o:b:a:r
read -d ''
使用 NUL字節作為分隔符。(當然與字元*
0
不同。)為什麼不使用之類的東西
-d '\0'
?-d '\x0'
嗯,這是個好問題。正如 Stéphane 評論的那樣,最初,ksh93
read -d
不支持read -d ''
這樣的,並且將其更改為支持反斜杠轉義將與原始版本不兼容。但是,如果您更喜歡它,您仍然可以使用read -d $'\0'
(同樣$'\t'
用於選項卡等)。只是在幕後,這與 相同-d ''
,因為 Bash 不支持字元串中的 NUL 字節。Zsh 可以,但它似乎同時接受-d ''
和-d $'\0'
。