我执行以下操作:
$ ./input ""
Run Code Online (Sandbox Code Playgroud)
输出:
argc 2
argv[1][0] 0
Run Code Online (Sandbox Code Playgroud)
但是,如果我想以基于程序的方式传递(几个)空引号:
$ python -c 'print "\"\""'
""
./input $(python -c 'print "\"\""')
Run Code Online (Sandbox Code Playgroud)
给出:
argc 2
argv[1][0] 22 - (22 hex value for ")
Run Code Online (Sandbox Code Playgroud)
那么我怎样才能生成类似的东西:
$ ./input "" "" "" ""
Run Code Online (Sandbox Code Playgroud)
并获得与示例 1 相同的结果?
在
./input $(cmd)
Run Code Online (Sandbox Code Playgroud)
因为,$(cmd)不加引号,这是一个 split+glob 运算符。shell 检索 的输出cmd,删除所有尾随换行符,然后根据$IFS特殊参数的值将其拆分,然后执行文件名生成(例如*.txt转换为当前目录中的非隐藏 txt 文件列表)结果词(后半部分不与zsh)并且在的情况下ksh也执行大括号扩展(例如a{b,c}变成ab和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)
Run Code Online (Sandbox Code Playgroud)
如果cmd输出a::b\n,那么 split+glob 运算符将导致"a",""和"b"参数(注意"s 不是值的一部分,我只是在这里使用它们来帮助显示值)。
使用a:b:\n,取决于外壳,这将导致"a"和"b"或"a","b"和""。您可以使用以下命令使其在所有 shell 中保持一致
./input $(cmd)""
Run Code Online (Sandbox Code Playgroud)
(这也意味着对于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)
Run Code Online (Sandbox Code Playgroud)
给出:
I got 3 arguments:
- <a b>
- <>
- < c>
Run Code Online (Sandbox Code Playgroud)
另请注意,当您执行以下操作时:
./input ""
Run Code Online (Sandbox Code Playgroud)
这些"是 shell 语法的一部分,它们是 shell 引用运算符。这些"字符不会传递给input.
¹ IFS 空白字符,每个 POSIX 是[:space:]在语言环境中分类的字符,$IFS尽管在 ksh88(POSIX 规范所基于的)和大多数 shell 中,这仍然仅限于 SPC、TAB 和 NL。我发现在这方面唯一符合 POSIX 的 shell 是yash. ksh93并且bash(从 5.0 开始)还包括其他空格(例如 CR、FF、VT...),但仅限于单字节(在某些系统上(例如 Solaris)要小心,其中包括单字节的不间断空格在某些地区)