引用符は、引数がスクリプトに渡される前に削除されるため、保持するには遅すぎます。できることは、引数を内部コマンドに渡すときにそれらの効果を保持し、印刷用に引用/エスケープされた引数の同等のバージョンを再構築することです.
内部コマンド "[email protected]"
に引数を渡すため -- 二重引用符を使用すると、[email protected] は元の単語の区切りを保持します。これは、内部コマンドがスクリプトとまったく同じ引数リストを受け取ることを意味します。
印刷の場合、bash の printf コマンドで %q 形式を使用して、引用符を再構築できます。これは常に元の引用を再構築するとは限りませんが、同等のものを構築することに注意してください。 引用/エスケープされた文字列。たとえば、引数 'uptime ; uname -a'
を渡した場合 uptime\ \;\ uname\ -a
を出力するかもしれません または "uptime ; uname -a"
またはその他の同等のもの (同様の例については、@William Pursell の回答を参照してください)。
これらの使用例は次のとおりです:
printf "Running command:"
printf " %q" innercmd "[email protected]" # note the space before %q -- this inserts spaces between arguments
printf "\n"
innercmd "[email protected]"
ユーザーがコマンドを次のように呼び出した場合:
./script 'foo'
スクリプトに与えられる最初の引数は文字列 foo
です 引用符なしで。スクリプトがそれと foo
を取得できる他の方法とを区別する方法はありません。 引数として (例:./script $(echo foo)
または ./script foo
または ./script "foo"
または ./script \f\o""''""o
)。
ユーザーがおそらく入力したものにできるだけ近い引数リストを出力したい場合:
#!/bin/bash
chars='[ !"#$&()*,;<>?\^`{|}]'
for arg
do
if [[ $arg == *\'* ]]
then
arg=\""$arg"\"
elif [[ $arg == *$chars* ]]
then
arg="'$arg'"
fi
allargs+=("$arg") # ${allargs[@]} is to be used only for printing
done
printf '%s\n' "${allargs[*]}"
完璧ではありません。 ''\''"'
のような引数 正当化されるよりも受け入れるのが難しい.