私は他の人(特にRed Hat)によって書かれたいくつかのスクリプトを見ました
VARIABLE1="${VARIABLE1:-some_val}"
。VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"
値を直接宣言する代わりにこの表記法を使用するのはなぜですかVARIABLE1=some_val
?
この表記法はどのような利点があるか、可能なエラーを防ぐのですか?
:-
この文脈に特別な意味がありますか?
答え1
この手法を使用すると、他の変数が空であるか定義されていない場合は、1つの変数に値を割り当てることができます。メモ:この「他の変数」は、同じ変数でも異なる変数でもよい。
抜粋
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted.
Otherwise, the value of parameter is substituted.
メモ:${parameter-word}
このフォームは次のとおり有効です。バッシュ文書、これらすべての拡張の場合:
コロンを省略すると、設定されていないパラメータのみがテストされます。つまり、コロンが含まれている場合、演算子は両方をテストします。範囲存在し、その値はnullではありません。コロンが省略された場合、演算子は存在をテストします。
Bashで利用可能なすべての型のパラメータ拡張の完全なリストについては、Bash HackerのWikiで次のトピックを確認することをお勧めします。パラメータ拡張」。
はい
変数が存在しません
$ echo "$VAR1"
$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value
変数が存在します
$ VAR1="has value"
$ echo "$VAR1"
has value
$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
has value
他の変数を評価するか、シンボルのデフォルトセクション内でコマンドを実行して同じことを実行できます。
$ VAR2="has another value"
$ echo "$VAR2"
has another value
$ echo "$VAR1"
$
$ VAR1="${VAR1:-$VAR2}"
$ echo "$VAR1"
has another value
その他の例
わずかに異なる表記法、つまりを使用することもできますVARX=${VARX-<def. value>}
。
$ echo "${VAR1-0}"
has another value
$ echo "${VAR2-0}"
has another value
$ echo "${VAR3-0}"
0
上記の$VAR1
& では$VAR2
"has another value" という文字列で定義しましたが、$VAR3
定義されていないのでデフォルト値を使用します0
。
他の例
$ VARX="${VAR3-0}"
$ echo "$VARX"
0
:=
シンボルの確認と割り当ての使用
最後に便宜演算子である:=
。テスト中の変数が空であるか定義されていない場合は、値を確認して割り当てます。
はい
これでこれが$VAR1
設定されました。オペレーターは、:=
1 回の作業でテストと配布を完了します。
$ unset VAR1
$ echo "$VAR1"
$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default
ただし、以前に値を設定した場合は変更されません。
$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value
便利なプレイボーイリファレンスシート
パラメータの設定と空ではありません | パラメータが設定されていますが空です。 | パラメーターが設定されていません。 | |
---|---|---|---|
${parameter:-word} |
変える範囲 | 変える言葉 | 変える言葉 |
${parameter-word} |
変える範囲 | 変える無効 | 変える言葉 |
${parameter:=word} |
変える範囲 | 分配する言葉 | 分配する言葉 |
${parameter=word} |
変える範囲 | 変える無効 | 分配する言葉 |
${parameter:?word} |
変える範囲 | エラー、終了 | エラー、終了 |
${parameter?word} |
変える範囲 | 変える無効 | エラー、終了 |
${parameter:+word} |
変える言葉 | 変える無効 | 変える無効 |
${parameter+word} |
変える言葉 | 変える言葉 | 変える無効 |
これの間に違いがあります仕事そして置換明示的:代入は変数の値を設定しますが、代入はしません。
引用する
答え2
@slm すでに含まれていますPOSIX ドキュメント- これは非常に役立ちますが、これらのパラメータを組み合わせて互いに影響を与える方法を実際に拡張することはありません。このフォームはここに記載されていません。
${var?if unset parent shell dies and this message is output to stderr}
これはから抜粋したものです。もう一つの答え私の考えでは、それがどのように機能するかをよく示していると思います。
sh <<-\CMD
_input_fn() { set -- "$@" #redundant
echo ${*?WHERES MY DATA?}
#echo is not necessary though
shift #sure hope we have more than $1 parameter
: ${*?WHERES MY DATA?} #: do nothing, gracefully
}
_input_fn heres some stuff
_input_fn one #here
# shell dies - third try doesnt run
_input_fn you there?
# END
CMD
heres some stuff
one
sh: line :5 *: WHERES MY DATA?
別の例は次のとおりです。同じ:
sh <<-\CMD
N= #N is NULL
_test=$N #_test is also NULL and
v="something you would rather do without"
( #this subshell dies
echo "v is ${v+set}: and its value is ${v:+not NULL}"
echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}"
${_test:+${N:?so you test for it with a little nesting}}
echo "sure wish we could do some other things"
)
( #this subshell does some other things
unset v #to ensure it is definitely unset
echo "But here v is ${v-unset}: ${v:+you certainly wont see this}"
echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}"
${_test:+${N:?is never substituted}}
echo "so now we can do some other things"
)
#and even though we set _test and unset v in the subshell
echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}"
# END
CMD
v is set: and its value is not NULL
So this $_test:= will equal something you would rather do without
sh: line 7: N: so you test for it with a little nesting
But here v is unset:
So this $_test:= will equal NULL
so now we can do some other things
_test is still NULL and v is still something you would rather do without
上記の例では、POSIXパラメータ置換の4つの形式とその変形の両方を利用しています。:colon null
またはnot null
テスト。上記のリンクにはより多くの情報があり、ここまた行く。
人々がしばしば考慮しないもう一つのこと${parameter:+expansion}
は、ここのドキュメントでそれがどれほど大きな役割を果たしているかです。ここに別の抜粋がありますその他の回答:
トップ
ここではいくつかのデフォルト値を設定し、呼び出し時に印刷する準備をします。
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
真ん中
結果に応じて、印刷機能を呼び出すためにここで他の機能を定義できます。
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
一番下
これですべての設定が完了したので、ここで結果を実行して抽出しましょう。
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
結果
理由は後で説明しますが、上記のコマンドを実行すると、次のような結果が表示されます。
_less_important_function()'s
最初の実行:あなたのお母さんの家に行って見ました。ディズニーオンアイス。
そうすれば書道あなたは成功するでしょう。
それから
_more_important_function():
私は行きました墓地ディズニーオンアイスも見ました。
そうすれば数学科外あなたは成功するでしょう。
_less_important_function()
再:墓地に行ってディズニーオンアイス(Disney on Ice)を見ました。
数学を課外すると後悔。
仕組み:
ここで重要な特徴はコンセプトです。conditional ${parameter} expansion.
変数が設定されていないか、nullの場合にのみ、次の形式を使用して変数を値に設定できます。
${var_name
:=desired_value}
設定されていない変数のみを設定したい場合は省略できます。:colon
そしてnull値はそのまま残ります。
範囲:
上記の例からわかるように、$PLACE
そして$RESULT
設定を通過したときに変更される内容parameter expansion
しかし、_top_of_script_pr()
呼び出されて、おそらく実行時に設定されているでしょう。これがうまくいく理由は_top_of_script_pr()
は( subshelled )
機能 - 含まれていますparens
代わりに{ curly braces }
他の人のために。サブシェルから呼び出されるため、設定するすべての変数は次のとおりです。locally scoped
この値は、親シェルに戻ると消えます。
しかし、時_more_important_function()
セット$ACTION
これはglobally scoped
だから影響を与える_less_important_function()'s
2回目のレビュー$ACTION
なぜなら_less_important_function()
セット$ACTION
通じるだけ${parameter:=expansion}.
答え3
個人的な経験。
私は時々値を一時的に上書きするためにスクリプトでこの形式を使用します。たとえば、次のような場合があります。
$ cat script.sh
SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING";
私は走ることができます:
$ env SOMETHING="something other than the default value" ./script.sh`
変更する必要のない元のデフォルト値ですSOMETHING
。
答え4
個々のコマンドライン引数を取得する興味深い方法は、$1、$2...スキームを使用することです。
echo "$1 $2 $3"
Two=$(2:-'default2')
echo "Second parameter: $Two"
パラメータとして呼び出される:ツリーに勝つ
結果:2番目のパラメータ:too
呼び出しパラメータ:5つ!
結果:2番目のパラメータ:default2