宣言が使用される場合、Bash変数は配列内で拡張されません。

宣言が使用される場合、Bash変数は配列内で拡張されません。

最近、私はbashの組み込みについてもっと読むことに決めましたdeclarelocalreadonly

local variable_name
variable_name='value'
readonly variable_name

到着する:

variable_name='value'
declare -r variable_name

この変更で作成する必要がある行数が減り、変数の値が整数であることをbashに通知するなど、いくつかのプロパティを設定できるようになりました。しかし、cURLエイリアスとして使用する関数を作成している間、配列内の変数は使用すると拡張されませんが、およびを使用するdeclareとうまく拡張されることがわかりました。localreadonly

例は次のとおりです。

#!/usr/bin/env bash

set -o errexit -o errtrace -o pipefail -o nounset
IFS=$'\n\t'

curl() {

  curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
  declare -r curl_version

  curl_args=(
    --user-agent "curl/${curl_version}"
    --silent
    --fail
  )

  command curl "${curl_args[@]}" \
    "${@}"

}

curl --url 'https://httpbin.org/get'

変数が何らかの理由で拡張されないため、--user-agent配列部分はbashが知っている限りバインドされていない変数ですset -o nounset

数日間働かせようとしたので、今タオルを投げて助けを求める時だと思いました。私が間違っていることを正しい方向に伝えることができる人はいますか?

編集する:

言及するのを忘れていましたが、たとえば、同じ行に変数を宣言するとdeclare -r variable_name問題が発生します。シェルチェック SC2155だから、値を設定した後に宣言しようとしています。

ベストアンサー1

そして:

curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
declare -r curl_version

関数で$curl_versionグローバル変数をいくつかの値に設定し、最初に設定されていない別々のローカル読み取り専用変数を作成します。

あなたが望むようです:

# instantiate a new local variable (but in bash it inherits the "export"
# attribute if any of the variable with same name in the parent scope)
local curl_version

# unset to remove that export attribute if any. Though you could
# also change the above to local +x curl_version
unset -v curl_version

# give a value:
curl_version="$(command curl --version | awk 'NR==1 {print $2}')"

# make that local variable read only
local -r curl_version

(変数をローカルにしたいことをより明確にするためlocalに、ここではnotを使用しました。)declare

または同時にすべての操作を実行します。

local +x -r curl_version="$(command curl --version | awk '{print $2; exit}')"

(shellcheckが指摘したように、それはパイプ²の終了状態を失います。)

とにかく私はCのようにシェルで/を使用しません。readonly特に、シェル(ksh93を除く)にはCなどの静的範囲がないためです。そして(インスタンスとは対照的に)グローバルスコープで読み取り専用に設定されている場合、関数のローカル変数を作成することはできません。typeset -rconstbashbashzsh

たとえば、

count() {
  local n
  for (( n = 0; n < $1; n++ )) { echo "$n"; }
}

readonly n=5
count "$n"

zshでは機能しますが、bashでは機能しません。ただ使用し、絶対に使用しないとlocal -r大丈夫でしょうreadonly


とにかくtypeset//declareではlocal同じですbash。唯一の違いは、local関数の外部で使用しようとするとエラーを報告することです。typeset -rとの違い(およびreadonly間と同じ)は、関数内で呼び出されると後者が新しい変数をインスタンス化しないことです。typeset -xexport

²exitそのバージョンでSIGPIPEで終了できる最初の行以降に入力処理を停止する方法を確認してください(出力が一度送信され、パイプに収まるので実際には不可能です)。それ以来、パイプは最終的に141シャットダウンで失敗する可能性があります。状態ですが、変数に値を割り当てることができる限り、それ自体はまだ成功します。awkawkcurlcurlpipefaillocal

おすすめ記事