最近、私はbashの組み込みについてもっと読むことに決めましたdeclare
。local
readonly
local variable_name
variable_name='value'
readonly variable_name
到着する:
variable_name='value'
declare -r variable_name
この変更で作成する必要がある行数が減り、変数の値が整数であることをbashに通知するなど、いくつかのプロパティを設定できるようになりました。しかし、cURLエイリアスとして使用する関数を作成している間、配列内の変数は使用すると拡張されませんが、およびを使用するdeclare
とうまく拡張されることがわかりました。local
readonly
例は次のとおりです。
#!/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 -r
const
bash
bash
zsh
たとえば、
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 -x
export
²exit
そのバージョンでSIGPIPEで終了できる最初の行以降に入力処理を停止する方法を確認してください(出力が一度送信され、パイプに収まるので実際には不可能です)。それ以来、パイプは最終的に141シャットダウンで失敗する可能性があります。状態ですが、変数に値を割り当てることができる限り、それ自体はまだ成功します。awk
awk
curl
curl
pipefail
local
答え2
関数の最初の行はグローバル変える
curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
関数の2行目は読み取り専用、空、ローカル変える
declare -r curl_version
このローカル変数はグローバル変数の値を置き換えます。
次の抜粋を参照してくださいhelp declare
。
関数内で使用すると、「declare」は「local」コマンドを使用するのと同じようにローカルに名前を作成します。 '-g'オプションはこの動作を抑制します。
私はこれをお勧めします:
curl() {
local -r curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
local curl_args=(
--user-agent "curl/${curl_version}"
--silent
--fail
)
command curl "${curl_args[@]}" \
"${@}"
}
変数を確認するには、declare -p curl_version curl_args
コマンドを呼び出す前に関数に変数を追加してください。