2

私は非常に広範なシェル スクリプトと、stackoverflow に関する調査を行って得た機能の一部を作成しました。私が実装したが、完全には理解できなかったものの 1 つは、 の使用ですset -- something

コマンドを読みましたhelp setが、次のシナリオでその実装がどのように機能するかを理解するのにまだ問題があります。

#!/bin/sh

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

もし私がそうしたら

set -- $params

そこでは一体何をしているのsetだろうか?

4

2 に答える 2

3

set -- "$(getopt abc:d: $*)"要するに、バグを作成することです。これは ; に固有のものではありませんが、 ;setの使用には必然的に付随的です。getoptただし、 の使用にも一般的です$*

次の点を考慮してください。

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

$*IFSすべての引数を 1 つの文字列にまとめます。その後、引用符が付けられていないため、これらの引数は:の内容に従って再び./filename with spaces3 つの引数 : ./filenamewith、 に分割されspacesます。そうしないでください。代わりに、http://mywiki.wooledge.org/BashFAQ/035 のプラクティスに従ってください(そうです、これは BashFAQ と呼ばれますが、POSIX 準拠のメカニズムと bash 固有のメカニズムをカバーしています)。

そうは言っても、何をするつもりなのかを議論するために、以下は実用的な例です:

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

getopt...そして、以下は、使用していない場合でも壊れている理由の例です(単一の引数が 2 つの別々の部分に分割される様子$*を参照してください):foo barfoobar

$ 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">

代わりに、引数リストに入れるアイテムのリストを管理する正しい方法は、配列を使用することです。POSIX sh では、これを行う正しい方法がまったく許可されていないためです。

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

これらの場合のいずれにおいても、引数ベクトル ( $@) は、 によって新しい内容で変更されset --、すべてのオプションの引数の後にのみ位置引数が配置され、 で区切られ--ます。ただし、間違って変更されています。複数単語の引数は文字列が分割され、間違って再結合されます。繰り返しますが、これを処理する正しい方法については、リンクされた FAQ を参照してください。

于 2013-06-24T16:32:59.960 に答える