2

我已经编写了一个相当广泛的 shell 脚本和一些通过在 stackoverflow 上进行研究而获得的功能。我实现但没有完全理解的一件事是使用set -- something.

我已经阅读了该help set命令,但我仍然无法理解它在以下场景中的实现方式:

#!/bin/sh

params="$(getopt abc:d: $*)"

如果我这样做

set -- $params

那里到底在set做什么?

4

2 回答 2

3

这在bash 手册页中有明确的介绍。

--

如果此选项后没有参数,则未设置位置参数。否则,位置参数将设置为参数,即使其中一些以“-”开头。

于 2013-06-24T16:24:07.280 回答
3

set -- "$(getopt abc:d: $*)"简而言之,就是制造错误。这并不特定于set,尽管使用getopt;必然是偶然的。但是,它也适用于$*.

考虑以下:

./yourscript -f"./filename with spaces"

$*将所有参数压缩到一个字符串中——之后,因为它没有被引用,所以这些参数根据IFS:的内容再次拆分./filename with spaces为三个参数:./filenamewithspaces. 不要那样做。相反,请遵循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分成两个单独的部分,foo以及bar):

$ getopt abc:d: -a -c "foo bar" baz
 -a -c foo bar -- baz

...以下是为什么set --不应该与字符串拆分一起使用的示例,这是如何将不带引号的扩展(例如$params)拆分为多个参数:

$ params='-f "foo bar"'
$ set -- $params
$ printf '<%s> ' "$@"; echo
<-a> <"foo> <bar">

相反,管理要放入参数列表的项目列表的正确方法是使用数组——一个 bash 扩展,因为 POSIX sh 根本不允许任何正确的方法来做到这一点:

$ params=( -f "foo bar" )
$ set -- "${params[@]}"
$ printf '<%s> ' "$@"; echo
<-a> <foo bar>

在任何这些情况下,参数向量 ( $@) 会随着新内容的set --, 更改,仅将位置参数放在所有可选参数之后,用 分隔--。但是,它的更改不正确:多字参数被字符串拆分并错误地重新组合。同样,请参阅链接的常见问题解答以了解处理此问题的正确方法。

于 2013-06-24T16:32:59.960 回答