我已经编写了一个相当广泛的shell脚本和我在stackoverflow上进行研究所获得的一些功能。我实施但未完全理解的一件事是使用set -- something
。
我已经阅读了help set
命令,但我仍然无法理解它在以下场景中的实现方式:
#!/bin/sh
params="$(getopt abc:d: $*)"
如果我那么
set -- $params
set
到底在做什么?
答案 0 :(得分:3)
bash man page明确涵盖了这一点。
-
如果此选项后面没有参数,则取消设置位置参数。否则,位置参数将设置为参数,即使其中一些参数以“ - ”开头。
答案 1 :(得分:3)
简而言之,set -- "$(getopt abc:d: $*)"
的作用是创建错误。这不是set
特有的,尽管使用getopt
一定是偶然的;但是,使用$*
也是通用的。
请考虑以下事项:
./yourscript -f"./filename with spaces"
$*
将所有参数压缩成一个字符串 - 之后,由于它没有引用,这些参数根据IFS
:./filename with spaces
的内容再次拆分为三个参数: ./filename
,with
和spaces
。不要那样做。相反,请遵循http://mywiki.wooledge.org/BashFAQ/035的做法(是的,它被称为BashFAQ,但它涵盖了POSIX兼容的机制以及特定于bash的机制)。
那就是说,要讨论它的目的是什么,以下是一个工作范例:
$ getopt abc:d: -a -c foo bar baz
-a -c foo -- bar baz
...以下是即使不使用getopt
时$*
被破坏的原因示例(请参阅单个参数foo bar
如何分成两个单独的部分,{ {1}}和foo
):
bar
...以下是为什么$ getopt abc:d: -a -c "foo bar" baz
-a -c foo bar -- baz
不应该与字符串拆分结合使用的示例,这就是不加引号的扩展(例如set --
)被拆分成的方式多个参数:
$params
相反,管理要放入参数列表的项列表的正确方法是使用数组 - 一个bash扩展,因为POSIX sh只是不允许任何正确的方法来执行此操作:
$ params='-f "foo bar"'
$ set -- $params
$ printf '<%s> ' "$@"; echo
<-a> <"foo> <bar">
在任何一种情况下,参数向量($ params=( -f "foo bar" )
$ set -- "${params[@]}"
$ printf '<%s> ' "$@"; echo
<-a> <foo bar>
)都会被$@
的新内容更改,只能在所有可选参数之后放置位置参数,由set --
分隔。然而,它发生了不正确的变化:多字参数被字符串拆分并错误地重新组合。再次,请参阅链接的常见问题解答以了解处理此问题的正确方法。