引用符で囲まれたパラメータを受け取って再渡すBashスクリプト


98

ネストされたスクリプトで安全に受け取れるように、bashスクリプトの引用符で囲まれたパラメータを取得しようとしています。何か案は?

test.sh

#!/bin/bash
echo $*
bash myecho.sh $*

myecho.sh

#!/bin/bash
 echo $1
 echo $2
 echo $3
 echo $4

サンプル:

bash test.sh aaa bbb '"ccc ddd"'

結果:

aaa bbb "ccc ddd"
aaa
bbb
"ccc
ddd"

欲しい結果

aaa bbb "ccc ddd"
aaa
bbb
ccc ddd

2
私はちょうどその質問をしようとしていました!良いタイミング。
スコッティT

回答:


70
#!/bin/bash
echo $*
bash myecho.sh "$@"

「$ @」構造はbash固有ではなく、どのPOSIXシェルでも機能することに注意してください(少なくともダッシュで機能します)。また、必要な出力があれば、追加の引用レベルはまったく必要ないことにも注意してください。IEは上記のスクリプトを次のように呼び出します。

./test.sh 1 2 "3 4"

5
「$ @」は、コーンおよびバッシュを含む、任意のボーンシェルまたはボーンシェル派生物(1978年以降)で機能します。おそらく95%の確率で、「$ @」の使用は正しく、$ *は間違っています。
ジョナサンレフラー

いいね!しかし、それを変数に「そのまま」格納する方法があるか誰か知っていますか?Original $@は関数内では使用できません(関数の引数によって上書きされるため)。私は試しfoovar="$@"foovar=$@+ "$foovar"関数を試してみましたが、どれもうまく
いき

143

"$ @"(ドルで引用)を使用して、パラメーターを添え字に渡します。そのようです ....

ls-color.sh:

#!/bin/bash
/bin/ls --color=auto "$@"    # passes though all CLI-args to 'ls'


理由について....

以下からのBashのmanページ

$*-1つから開始して、位置パラメーターに展開します。展開が二重引用符内で発生すると、IFS特殊変数の最初の文字で区切られた各パラメーターの値を含む単一の単語に展開されます。つまり、"$*"と同等です "$1c$2c..."。ここで、cはIFS変数の値の最初の文字です。IFSが設定されていない場合、パラメーターはスペースで区切られます。IFSがnullの場合、パラメーターはセパレーターを介さずに結合されます。

$@-1つから開始して、位置パラメーターに展開します。展開が二重引用符で囲まれている場合、各パラメーターは個別の単語に展開されます。、されていること"$@"と等価である"$1" "$2" ...二重引用符で囲まれた拡張は、単語内で発生した場合、最初のパラメータの拡張は、元の単語の先頭部分と結合され、そして最後のパラメータの拡張は、元の最後の部分で接合され、語。そこには位置パラメータがない、とき "$@"$@何も展開する(すなわち、それらは削除されます)。


デモスクリプトの設定...

echo 'echo -e "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4"' > echo-params.sh
echo './echo-params.sh $*' > dollar-star.sh
echo './echo-params.sh $@' > dollar-at.sh
echo './echo-params.sh "$*"' > quoted-dollar-star.sh
echo './echo-params.sh "$@"' > quoted-dollar-at.sh
chmod +x *.sh

"$@"-quoted-dollar-atは、引数をサブシェルに再渡すための恒等変換です(時間の約99%、これはあなたがやろうとしていたことです):

./quoted-dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2=            
  # $3= 'cc cc'
  # $4= "ddd ddd"

"$*"-quoted -dollar-star は、引数を1つの文字列に分割します (たとえば、条件付きで、この動作が実際に必要な時間の約1%:)if [[ -z "$*" ]]; then ...

./quoted-dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa  'cc cc' "ddd ddd"   
  # $2=                     
  # $3=             
  # $4=

$*/ $@-引用符なしで、どちらの形式も1レベルの引用符を取り除き、基になる文字列からスペースを解釈しますが、引用符文字は無視します(ほとんどの場合、これは間違いです)。

./dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc                  
  # $3= cc'
  # $4= "ddd

./dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc
  # $3= cc'
  # $4= "ddd

楽しみたい場合は、「$ @」を使用して好きなだけネストできるので、必要に応じて要素を引数スタックからプッシュしたりポップしたりできます。

function identity() {
  "$@"
}
set -x
identity identity identity identity identity echo Hello \"World\"
# + identity identity identity identity identity echo Hello '"World"'
# + identity identity identity identity echo Hello '"World"'
# + identity identity identity echo Hello '"World"'
# + identity identity echo Hello '"World"'
# + identity echo Hello '"World"'
# + echo Hello '"World"'
# Hello "World"

1
説明ありがとう。grepエイリアスに「$ *」を使用しただけです。
ダークレス2013

あなたは私の日を救います!
xyz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.