ShellCheck は、実際には二重引用符で囲まれているのに、式が二重引用符で囲まれていないと文句を言います。なぜでしょうか?

ShellCheck は、実際には二重引用符で囲まれているのに、式が二重引用符で囲まれていないと文句を言います。なぜでしょうか?

AWS CLI を使用して bash スクリプトを作成しているのですが、shellcheck間違っていると思われるエラーが発生します。なぜエラーが発生するのかを解明したいと思います。

コードとエラーメッセージは次のとおりです。

for server in $(${aws} ec2 describe-instances --query 'Reservations[].Instances[][].{Name: Tags[?Key==`Name`].Value[] | [0]}' --filters "Name=tag:Name,Values=${server_name}*" --output text);
                                                                                                                                                                            ^-- SC2016: Expressions don't expand in single quotes, use double quotes for that.

SO エディタでコードを正しく整列させることができませんが、 はコード内の^--を指しています。 この部分:*

"Name=tag:Name,Values=${server_name}*"

エラーはShellCheckドキュメントへのリンク参考までに、すべてを再確認したところ、準拠しているようです。:D

が問題を引き起こしていると推測しており*、これを回避できることはわかっていますshellcheck -e SC2016が、shellcheck が carp する原因が何なのか本当に疑問に思っています。

何か案は?

答え1

これは誤検知ですが、あなたが考えているものではありません。 とは関係ありません*し、私の場合はそこを指していませんでした。 は`Name`、一重引用符の中にあることに問題があります。 たとえば、 はecho '`Name`'同じ警告を生成します。バックティックを評価する必要があると考えて、評価されないことを警告しているからです。

答え2

回答ではありませんが、フォーマットされたコメントです:

for厳密に言うと、ループではなくループを使用する必要がありますwhile read

while IFS= read -r server; do
    : do stuff here
done < <(
    "$aws" ec2 describe-instances \
        --query 'Reservations[].Instances[][].{Name: Tags[?Key==`Name`].Value[] | [0]}' \
        --filters "Name=tag:Name,Values=${server_name}*" \
        --output text
)

forループは空白で区切られて読み取られる言葉whileループ読み取り- 見るhttp://mywiki.wooledge.org/BashFAQ/001

代わりに、readarray出力をキャプチャするために使用します

readaray -t servers < <(
    "$aws" ec2 describe-instances \
        --query 'Reservations[].Instances[][].{Name: Tags[?Key==`Name`].Value[] | [0]}' \
        --filters "Name=tag:Name,Values=${server_name}*" \
        --output text
)

for server in "${servers}"; do ...; done

最後に、長くて読みにくいコマンドの場合は、オプションを配列に保存すると読みやすさが向上します。

opts=(
    --query 'Reservations[].Instances[][].{Name: Tags[?Key==`Name`].Value[] | [0]}' 
    --filters "Name=tag:Name,Values=${server_name}*"
    --output text
)

readarray -t servers < <("$aws" ec2 describe-instances "${opts[@]}")

関連情報