我正在尝试调试我的 shell 脚本:
content_type='-H "Content-Type: application/json"'
curl $content_type -d "{"test": "test"}" example.com
我了解到这并没有达到我的预期。在此脚本中,传递给curl
(由于)的参数$content_type
是:
-H
"Content-Type:
application/json"
而不是(我所期望的):
-H
Content-Type: application/json
我知道我可以编写如下脚本:
content_type="Content-Type: application/json"
curl -H "$content_type" -d "{"test": "test"}" example.com
它会以这种方式工作,但我想知道是否可以在单个变量中保存包含参数的多个空间。
对于第二个(工作)版本,如果我想排除内容类型,我需要删除两件事:-H
和$content_type
。
但是,我想知道是否可以将选项及其值放入单个实体中,以便排除/包含内容类型将导致删除/添加单个实体。
使用数组是不可移植的,因为 POSIX 中没有数组。
为什么第一个方法会这样?
原因是分词。当我们定义content_type
如下时:
content_type='-H "Content-Type: application/json"'
它具有以下价值:
-H "Content-Type: application/json"
当我们引用不带引号的变量(即,$content_type
而不是"$content_type"
)时,扩展值将成为分词的主题。从分词页面bash 手册:
shell 扫描未出现在双引号内的参数扩展、命令替换和算术扩展的结果以进行分词。
来自同一页面:
shell 将 的每个字符
$IFS
视为分隔符,并使用这些字符作为字段终止符将其他扩展的结果拆分为单词。如果 IFS 未设置,或其值恰好为<space><tab><newline>
,则默认...
因此,通过用作分隔-H "Content-Type: application/json"
符来分割。<space><tab><newline>
这给了我们:
-H
"Content-Type:
application/json"
答案1
有一标准 shell 中的标准数组式结构。它是位置参数。所以一个可能的解决方案是使用set -- …
和"$@"
。在你的情况下你会这样做:
set -- -H "Content-Type: application/json"
curl "$@" -d "{"test": "test"}" example.com
请注意,这会限制您只能使用一个可用阵列。例如,您不能将一个用于curl,而另一个用于另一个程序。当然,它会破坏脚本的参数。
答案2
复制相关部分吉尔斯的回答:
如何将命令存储在变量中?
“命令”可以表示三件事:命令名称(可执行文件的名称,带或不带完整路径,或函数名称,内置或别名),带参数的命令名称,或一段 shell 代码。因此有不同的方式将它们存储在变量中。
如果您有命令名称,只需存储它并像平常一样使用带有双引号的变量即可。
command_path="$1" … "$command_path" --option --message="hello world"
如果您有一个带参数的命令,则问题与上面的文件名列表相同:这是一个字符串列表,而不是一个字符串。您不能将参数填充到一个中间有空格的字符串中,因为如果这样做,您将无法区分作为参数一部分的空格和分隔参数的空格之间的区别。如果您的 shell 有数组,则可以使用它们。
cmd=(/path/to/executable --option --message="hello world" --) cmd=("${cmd[@]}" "$file1" "$file2") "${cmd[@]}"
如果您使用的 shell 没有数组怎么办?如果您不介意修改位置参数,您仍然可以使用它们。
set -- /path/to/executable --option --message="hello world" -- set -- "$@" "$file1" "$file2" "$@"
如果您需要存储复杂的 shell 命令(例如重定向、管道等)怎么办?或者如果您不想修改位置参数?然后您可以构建一个包含该命令的字符串,并使用
eval
内置命令。code='/path/to/executable --option --message="hello world" -- /path/to/file1 | grep "interesting stuff"' eval "$code"
我建议任何人阅读全文吉尔斯的回答尽管。它包含大量有用的信息。