スクリプトでの変数の割り当てに「$ {a:-b}」を使用する


427

私は他の人が書いたいくつかのスクリプト(特にRed Hat)を見てきましたが、それらの変数の多くは次の表記法を使用して割り当てられる VARIABLE1="${VARIABLE1:-some_val}" か、他の変数を展開します VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

値を直接宣言するだけでなく、この表記法を使用する意味は何ですか(例:)VARIABLE1=some_val

この表記法や、防止される可能性のあるエラーには利点がありますか?

:-このコンテキストで特定の意味を持っていますか?


をご覧くださいman bash。ブロック「Parameter Expansion」を検索します(約28%)。これらの割り当ては、たとえばデフォルト機能です。「まだ設定されていない場合にのみデフォルト値を使用します。」
Hauke Laging

回答:


697

この手法により、別の変数が空または未定義の場合に、変数に値を割り当てることができます。注:この「その他の変数」は、同じ変数または別の変数にすることができます。

抜粋

${parameter:-word}
    If parameter is unset or null, the expansion of word is substituted. 
    Otherwise, the value of parameter is substituted.

注:このフォームも機能し${parameter-word}ます。Bash内で利用可能なすべての形式のパラメーター拡張の完全なリストをご覧になりたい場合は、Bash HackerのWikiタイトル「Parameter expansion」でこのトピックをご覧になることを強くお勧めします。

変数が存在しません
$ 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が設定されたことに注意してください。オペレーター:=は、単一の操作でテストと割り当てを行いました。

$ unset VAR1
$ echo "$VAR1"

$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default

ただし、値が事前に設定されている場合は、そのまま残されます。

$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value

ハンディダンディ参照表

    ss of table

参照資料


8
これらすべてが拡張であるとは限らないことに注意してくださいbash${var:-word}Q内の1つのですが、ありません${var-word}上記の。POSIXのドキュメントには素晴らしい表がありますが、この回答にそれをコピーする価値があるかもしれません-pubs.opengroup.org/onlinepubs/9699919799/utilities/…–
Graeme

5
@Graeme、それは文書化されています、設定されていないパラメータのみのテストでコロンを省略
ステファンシャゼル

7
echo "${FOO:=default}"実際に使用したい場合は、使用するのが最適ですecho。しかし、そうでない場合は、:組み込みを試してください... : ${FOO:=default} あなた$FOOdefault上記のように設定されています(つまり、まだ設定されていない場合)。しかし$FOO、そのプロセスには反響はありません。
fbicknel

2
[OK]を、その答えを見つけた:stackoverflow.com/q/24405606/1172302を。を使用して${4:-$VAR}動作します。
ニコスアレクサン

1
ここに、500をもたらすために+1があります。おめでとうございます!:)
XtraSimplicity

17

@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

上記の例では、4つの形式のPOSIXパラメーター置換とそれらのさまざまな:colon nullor 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() 再び:

私は墓地に行き、ディズニー・オン・アイスを見ました。

修正数学を行う場合、それ後悔します。

使い方:

ここでの主要な機能は、次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の第二の評価$ACTION理由_less_important_function()のセット$ACTIONのみを経由し${parameter:=expansion}.


1
Bourne Shell
Sridhar Sarnobat

8

個人的体験。

私は、スクリプトで時々この形式を使用して、値のアドホックなオーバーライドを行います。

$ cat script.sh
SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

走れる:

$ env SOMETHING="something other than the default value" ./script.sh` 

の元のデフォルト値を変更する必要はありませんSOMETHING

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.