將生成的空字元串作為命令行參數傳遞
我執行以下操作:
$ ./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}
變成ab
andac
)。的預設值
$IFS
包含 SPC、TAB 和 NL 字元(在 中也是 NULzsh
,其他 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 等某些系統上要小心,其中包括單字節的不間斷空格在某些地區)