私はこのようなことをしたい。
$ touch a\ b
$ cmd=cat\ a\ b
$ echo $cmd
cat a b
$cmd
cat: a: No such file or directory
cat: b: No such file or directory
ファイルにスペースに問題がありますa b
。だからこれを試しました。
$ cmd=cat\ a\\\ b
$ echo $cmd
cat a\ b
$ $cmd
cat: a\': No such file or directory
cat: b: No such file or directory
これも失敗しました。$cmd
猫が走らないようにするにはどうすればよいですかa b
?
答え1
set -- cat "a b"
"$@"
これはcat
単一の引数で実行されますa b
。拡張"$@"
(二重引用符を含む!)は、個別に引用された位置パラメータのリストになります。位置パラメータはで設定されますset
。
ただし、コマンド名がリスト自体に含まれることはまれです。もっと一般的になる
set -- "a b"
cat "$@"
または、実際のコマンド名変数を保持するには
cmd=cat
set -- "a b"
"$cmd" "$@"
ファイル名オペランドを設定してコマンドを実行する間にコマンドにさらにファイル名またはオプションを追加するには、次のように変更します$@
。
cmd=cat
set -- "a b"
# later (adding more files to the end):
set -- "$@" "more files" "some glob here-"[0-9]
# later (adding an option at the front):
set -- -v "$@"
"$cmd" "$@"
$@
コマンド名がすでに存在する場合は、前にコマンド名を追加することは困難です。このような場合は、shift
一時的にコマンド名を$@
別の変数に入れて追加したいものを追加してから、コマンド名を再度追加する必要があります。
cmd=$1
shift
set -- "$cmd" -v "$@"
通常、位置パラメータを設定するset --
よりも使用したいです。コマンドライン引数リストで、この時点以降のコマンドラインオプションを取得するコマンドラインオプションパーサーを停止しますset
。--
がなければ、まったく異なる場合のように、文字列の前にwithを追加する--
ことは不可能です。-v
$@
set
set -v
関連:
答え2
引用符を有効または無効にするecho $cmd
と$cmd
、コンテンツは分割+グローブを呼び出します$cmd
。これはecho cat a b
、シェルの構文解析を使用してに渡された別の引数に分割したcat
ときa
に発生する状況とは関係ありません。b
echo
Split + globの分割はSPCの基本的な埋め込みに基づいているため、$IFS
分割単語にSPCは含まれません。別の区切り文字を使用する必要があります。
IFS=: # split on :
set -o noglob # disable glob part
cmd='cat:a b'
printf '<%s>\n' $cmd # split+glob
$cmd # split+glob
cmd
eval
あるいは、分割+globに依存するのではなく、シェルコマンドライン(シェル言語のコード)を含めて呼び出してそのコードを解釈することもできます。
cmd='cat "a b"'
eval "$cmd" # note the quotes to disable split+glob