エココマンド

エココマンド

ENV変数を保存するためにCircleCiボックスを使用しようとしています。私は通常そうします:

echo 'export FILE=$(ls bin | head -n 1)' >> $BASH_ENV

これは単純なコマンドに適しており、$ BASH_ENVに出力を生成します。

export FILE=$(ls bin | head -n 1)

これで一度だけ実行できる拡張コマンドの場合、これは複雑で動作しません。

echo 'export INSTANCE_ID=$(aws ec2 run-instances --instance-type t3.large\
--image-id $AMI --key-name circleci-key --count 1 --security-group-ids $SG\
--subnet-id $SUBNET --network-interfaces "{\"AssociatePublicIpAddress\": true, \"DeviceIndex\": 0, \"SubnetId\": \"$SUBNET\", \"Groups\": [\"$SG\"]}"\
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=instance-from-circleci}]'\
 | jq '.Instances[0].InstanceId' --raw-output)' >> $BASH_ENV

このコードは、$ BASH_ENVに追加されると実行されるたびに実行されますsource $BASH_ENV

この値を変数に保存し、既に最終形式のエコー行に追加する方法はありますか?

それは次のとおりです。

echo 'export $INSTANCE_ID' >> $BASH_ENV

答え1

引用符をエスケープする手間を避けるには、次の文書を使用する方が簡単です。

cat << 'EOF' >> "$BASH_ENV"
export INSTANCE_ID="$(
  aws ec2 run-instances \
    --instance-type t3.large \
    --image-id "$AMI" \
    --key-name circleci-key \
    --count 1 \
    --security-group-ids "$SG" \
    --subnet-id "$SUBNET" \
    --network-interfaces '
      {
        "AssociatePublicIpAddress": true,
        "DeviceIndex": 0,
        "SubnetId": "'"$SUBNET"'",
        "Groups": ["'"$SG"'"]
      }' \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=instance-from-circleci}]' |
  jq '.Instances[0].InstanceId' --raw-output)"
EOF

(また、欠落している引用符を修正し、読みやすさを向上させます。)

EOF()周囲の引用符が'EOF'重要です。これがないと、この文書の変数とコマンドの置換が拡張され、\この文書を生成するときに尾が行の連続として処理されます。

答え2

今一度実行するだけの拡張コマンドの場合、[...]この値を変数に保存してから、既に最終形式のエコーラインに追加する方法はありますか?

デフォルトでは、セクションを$ BASH_ENVとして印刷するのではなく、スクリプト自体var=$(command...)でコマンド置換を実行してから結果を印刷します。だから:

var=$(some command)
echo "var='$var'" >> file

しかし、これはvar='value'シェルの引用などを経ることになりますので、値に一重引用符が含まれれば壊れます。

代わりにprintf %q、Bashでは、たとえば、次のように使用できます。

var=$(some command)
printf "var=%q\n" "$var" >> file

たとえば、値が$var次の場合にit ain't so生成されます。var=var=it\ ain\'t\ so見苦しいですが、実行時に同じ値を生成します。

関連情報