実行中に変数を引用する必要がありますか?

実行中に変数を引用する必要がありますか?

シェルスクリプトの一般的な規則は、特別な理由がない限り、常に変数を引用する必要があることです。詳細については、次のQ&Aをご覧ください。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク

ただし、次の機能を検討してください。

run_this(){
    $@
}

そこに引用する必要がありますか$@?私はしばらく遊んでいましたが、引用符の欠落によって問題が発生した状況を見つけることができませんでした。一方、引用符を使用すると、スペースを含むコマンドを引用符で囲まれた変数に渡すと問題が発生します。

#!/usr/bin/sh
set -x
run_this(){
    $@
}
run_that(){
    "$@"
}
comm="ls -l"
run_this "$comm"
run_that "$comm"

上記のスクリプトを実行すると、次のものが返されます。

$ a.sh
+ comm='ls -l'
+ run_this 'ls -l'
+ ls -l
total 8
-rw-r--r-- 1 terdon users  0 Dec 22 12:58 da
-rw-r--r-- 1 terdon users 45 Dec 22 13:33 file
-rw-r--r-- 1 terdon users 43 Dec 22 12:38 file~
+ run_that 'ls -l'
+ 'ls -l'
/home/terdon/scripts/a.sh: line 7: ls -l: command not found

run_that $comm代わりに、この問題を解決することができますが、(参照されていない)関数は両方とも機能するため、run_that "$comm"これrun_thisはより安全なオプションのようです。

それでは、$@コマンドで実行される関数で使用される具体的なケースでは、引用符で囲む必要がありますか?引用しなければならない理由や引用すべきではない理由を説明し、引用を壊す可能性があるデータの例を示します。$@$@

ベストアンサー1

問題は、コマンドが関数に渡される方法です。

$ run_this ls -l Untitled\ Document.pdf 
ls: cannot access Untitled: No such file or directory
ls: cannot access Document.pdf: No such file or directory
$ run_that ls -l Untitled\ Document.pdf 
-rw------- 1 muru muru 33879 Dec 20 11:09 Untitled Document.pdf

"$@"as inrun_thatは、関数の前に一般的に書かれたコマンド(上記のように)がプレフィックスで付けられる一般的な場合に使用する必要があります。

引用符のない文字を使用しようとすると、スペースを含むファイル名は渡され$@ませrun_thisん。次の試みのいずれも機能しません。

$ run_this 'ls -l Untitled\ Document.pdf'
ls: cannot access Untitled\: No such file or directory
ls: cannot access Document.pdf: No such file or directory
$ run_this 'ls -l "Untitled\ Document.pdf"'
ls: cannot access "Untitled\: No such file or directory
ls: cannot access Document.pdf": No such file or directory
$ run_this 'ls -l Untitled Document.pdf'
ls: cannot access Untitled: No such file or directory
ls: cannot access Document.pdf: No such file or directory
$ run_this 'ls -l' 'Untitled Document.pdf'
ls: cannot access Untitled: No such file or directory
ls: cannot access Document.pdf: No such file or directory

うまくいかないのは、引用符のない拡張子が単語分割を通過してスペースに分割され、引用符などを解釈する方法を提供しないためです(これを使用する必要がありますeval)。

たとえば、参照してください。

おすすめ記事