web-dev-qa-db-ja.com

「-c」オプション文字列の後に引数を指定してBash「-c」オプションを使用できないようです

Bashのmanページには、-cオプションに関して次のように書かれています。

-c string-cオプションが存在する場合、コマンドはstringから読み取られます。文字列の後に引数がある場合、それらは$0で始まる位置パラメータに割り当てられます。

したがって、その説明があれば、このようなものが機能するはずだと思います。

bash -c "echo arg 0: $0, arg 1: $1" arg1

ただし、出力には次のように表示されるため、-c文字列の後の引数が位置パラメータに割り当てられていないように見えます。

arg 0: -bash, arg 1:

私はかなり古いBashを実行しています(Fedora 4で):

[root @ dd42 trunk] #bash --version GNU bash、バージョン3.00.16(1)-リリース(i386-redhat-linux-gnu)Copyright(C)2004 Free Software Foundation、株式会社.

私は実際に、引数を使用してシェルスクリプトを少し実行しようとしています。 -cは非常に有望に見えると思ったので、上記の問題が発生しました。 evalを使用することを考えましたが、evalに続くものに引数を渡すことはできないと思います。私は他の提案も受け入れています。

28
Chris Markle

呼び出し元のシェルで補間が発生しないようにするには、一重引用符を使用する必要があります。

$ bash -c 'echo arg 0: $0, arg 1: $1' arg1 arg2
arg 0: arg1, arg 1: arg2

または、二重引用符で囲まれた文字列内の変数をエスケープします。どちらを使用するかは、コードスニペットに何を入れたいかによって異なります。

35
martin clayton

文字列内の「$0」と「$1」は、それぞれ変数#0と#1に置き換えられるためです。

試してみてください:

bash -c "echo arg 0: \$0, arg 1: \$1" arg0 arg1

このコードでは、両方の$がエスケープされているため、ベースはそれを文字列$と見なし、置き換えられません。

このコマンドの結果は次のとおりです。

arg 0: arg0, arg 1: arg1

お役に立てれば。

4
NawaMan

$0(つまり、\$0)に円記号を追加します。そうしないと、現在のシェルは、サブシェルに到達する前に、シェルの名前に$0をエスケープします。

2
tyranid

martinは補間について正しいです:一重引用符を使用する必要があります。ただし、実行中のコマンドに引数を渡そうとしている場合は、文字列within文字列で、明示的に転送する必要があることに注意してください。たとえば、スクリプトがある場合foo.sh次のようになります:

#!/bin/bash
echo 0:$0
echo 1:$1
echo 2:$2

次に、次のように呼び出す必要があります

$ bash -c './foo.sh ${1+"$@"}' foo "bar baz"
0:./foo.sh
1:bar baz
2:

またはより一般的にはbash -c '${0} ${1+"$@"}' <command> [argument]...

これは好きではありません

$ bash -c ./foo.sh foo "bar baz"
0:./foo.sh
1:
2:

これも好きではない

$ bash -c './foo.sh $@' foo "bar baz"
0:./foo.sh
1:bar
2:baz

つまり、サブプロセスをコマンド文字列に埋め込んだり、エスケープしたりすることなく、引数をサブプロセスに渡すことができます。

2
z0r