Bash

將生成的空字元串作為命令行參數傳遞

  • March 16, 2021

我執行以下操作:

$ ./input ""

輸出:

argc 2
argv[1][0] 0

但是,如果我想以基於程序的方式傳遞(幾個)空引號:

$ python -c 'print "\"\""'
""

./input $(python -c 'print "\"\""')

給出:

argc 2
argv[1][0] 22 - (22 hex value for ")

那麼我怎樣才能生成類似的東西:

$ ./input "" "" "" ""

並獲得與範例 1 相同的結果?

./input $(cmd)

因為,$(cmd)未加引號,所以這是一個 split+glob 運算符。shell 檢索 的輸出cmd,刪除所有尾隨換行符,然後根據$IFS特殊參數的值將其拆分,然後執行文件名生成(例如變成*.txt目前目錄中的非隱藏 txt 文件列表)結果詞(後半部分不帶zsh)並且在的情況下ksh也執行大括號擴展(例如a{b,c}變成aband ac)。

的預設值$IFS包含 SPC、TAB 和 NL 字元(在 中也是 NUL zsh,其他 shell 要麼刪除 NUL,要麼扼殺牠們)。那些(不是 NUL)也恰好是 IFS 空白字元¹,在 IFS 拆分時會被特殊處理。

如果輸出cmd" a b\nc \n",則 split+glob 運算符將生成一個"a","b""c"參數./input。使用 IFS 空白字元,不可能split+glob生成空參數,因為一個或多個 IFS 空白字元的序列被視為一個分隔符。要生成一個空參數,您需要選擇一個不是 IFS 空白字元的分隔符。實際上,任何非空白字元都可以(最好也避免此處所有 shell 不支持的多字節字元)。

因此,例如,如果您這樣做:

IFS=:          # split on ":" which is not an IFS-whitespace character
set -o noglob  # disable globbing (also brace expansion in ksh)
./input $(cmd)

如果cmd輸出a::b\n,則 split+glob 運算符將產生"a","""b"參數(請注意,"s 不是值的一部分,我只是在這裡使用它們來幫助顯示值)。

使用a:b:\n,取決於外殼,這將導致"a"and"b""a", "b"and ""。您可以使其在所有外殼中保持一致

./input $(cmd)""

(這也意味著對於cmd(或僅由換行符組成的輸出)的空輸出,./input將接收一個空參數,而不是根本沒有參數)。

例子:

cmd() {
 printf 'a b:: c\n'
}
input() {
 printf 'I got %d arguments:\n' "$#"
 [ "$#" -eq 0 ] || printf ' - <%s>\n' "$@"
}
IFS=:
set -o noglob
input $(cmd)

給出:

I got 3 arguments:
- <a b>
- <>
- < c>

另請注意,當您這樣做時:

./input ""

這些"是 shell 語法的一部分,它們是 shell 引用運算符。這些"字元不會傳遞給input.


¹ IFS 空白字元,每個 POSIX 是分類為[:space:]區域設置的字元,並且碰巧$IFS在 ksh88(POSIX 規範所基於的)和大多數 shell 中,仍然僅限於 SPC、TAB 和 NL。在這方面我發現的唯一符合 POSIX 的外殼是yash. ksh93並且bash(從 5.0 開始)還包括其他空格(例如 CR、FF、VT…),但僅限於單字節空格(在 Solaris 等某些系統上要小心,其中包括單字節的不間斷空格在某些地區)

引用自:https://unix.stackexchange.com/questions/496843