28

簡単な Bash 変数のテストは次のようになります。

${varName:?    "${varName} is not defined"}

これを関数に入れて再利用したいと思います。どうすればいいですか?

以下は失敗します

#
# Test a variable exists
tvar(){
 val=${1:?    "${1}    must be defined, preferably in $basedir"}
 if [ -z ${val}  ]
     then
     echo Zero length value
 else
     echo ${1} exists, value ${1}
 fi
}

つまり、テストが失敗した場合は終了する必要があります。

4

7 に答える 7

46

lhunath の回答のおかげで、man何百回も見落としていた Bash ページの一部にたどり着きました。

    部分文字列展開を実行しない場合、bash は以下のパラメーターをテストします。
    設定されていないか、null です。コロンを省略すると、パラメーターのみのテストになります。
    設定されていません。

これにより、次の真理値表を作成するようになりました。

                | | 設定解除 | セット | 設定して | 意味
                | | | | しかしヌル | null ではない |
    ============+=======+==========+==========+======= ======================
     ${var-_} | T | T | ふ | T | T | null でないか、設定されていません
    ------------+---------+----------+----------+------- ----------------------
     ${var:-_} | T | T | T | T | T | T | 常に真です。subst に使用します。
    ------------+---------+----------+----------+------- ----------------------
     $var | ふ | ふ | T | T | var が設定されており、null ではない
    ------------+---------+----------+----------+------- ----------------------
     ${!var[@]} | ふ | T | T | T | T | varが設定されています

この表は、最後の行の仕様を紹介しています。Bashmanページには、「name が配列でない場合、name が設定されている場合は 0 に展開され、それ以外の場合は null に展開されます」と記載されています。この真理値表では、配列であっても同じように動作します。

于 2009-09-24T02:04:30.513 に答える
19

あなたが探しているのは間接的です。

assertNotEmpty() {
    : "${!1:? "$1 is empty, aborting."}"
}

これにより、次のようなことを行うと、スクリプトがエラー メッセージで中止されます。

$ foo=""
$ assertNotEmpty foo
bash: !1:  foo is empty, aborting.

が空かどうかだけをテストしたい場合fooは、スクリプトを中止する代わりに、関数の代わりにこれを使用します。

[[ $foo ]]

例えば:

until read -p "What is your name? " name && [[ $name ]]; do
    echo "You didn't enter your name.  Please, try again." >&2
done

また、空のパラメーターと設定されていないパラメーターの間には非常に重要な違いがあることに注意してください。これらの用語を混同しないように注意してください。空のパラメーターは、設定されているものの、空の文字列に設定されているだけです。設定されていないパラメーターは、まったく存在しないパラメーターです。

前の例はすべて、空のパラメーターをテストします。設定されていないパラメータをテストし、設定されているすべてのパラメータが空かどうかにかかわらず OK であると見なす場合は、次のようにします。

[[ ! $foo && ${foo-_} ]]

次のような関数で使用します。

assertIsSet() {
    [[ ! ${!1} && ${!1-_} ]] && {
        echo "$1 is not set, aborting." >&2
        exit 1
    }
}

渡すパラメーター名が設定されていないパラメーターを示す場合にのみ、スクリプトを中止します。

$ ( foo="blah"; assertIsSet foo; echo "Still running." )
Still running.
$ ( foo=""; assertIsSet foo; echo "Still running." )
Still running.
$ ( unset foo; assertIsSet foo; echo "Still running." )
foo is not set, aborting.
于 2009-05-17T12:36:17.467 に答える
5

使いたい[ -z ${parameter+word} ]

の一部man bash:

Parameter Expansion
    ...
    In each of the cases below, word is subject to
    tilde expansion, parameter expansion, command
    substitution, and arithmetic expansion.  When
    not performing substring expansion, bash
    tests for a parameter that is unset or
    null; omitting the colon results in a
    test only for a parameter that is unset.
    ...
    ${parameter:+word}
           Use Alternate Value.  If parameter is
           null or unset, nothing is substituted,
           otherwise the expansion of word is
           substituted.
    ...

言い換えると:

${parameter+word}
       Use Alternate Value.  If parameter is unset,
       nothing is substituted, otherwise the
       expansion of word is substituted.

いくつかの例:

$ set | grep FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$ declare FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=1
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ unset FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
于 2012-11-26T19:35:23.797 に答える
3

この関数は、現在設定されている変数をテストします。変数は配列の場合もあります。Bash では、0 == TRUE、1 == FALSE であることに注意してください。

function var.defined {
    eval '[[ ${!'$1'[@]} ]]'
}

# Typical usage of var.defined {}

declare you="Your Name Here" ref='you';

read -p "What's your name: " you;

if var.defined you; then   # Simple demo using literal text

    echo "BASH recognizes $you";
    echo "BASH also knows a reference to $ref as ${!ref}, by indirection.";

fi

unset you # Have just been killed by a master :D

if ! var.defined $ref; then    # Standard demo using an expanded literal value

    echo "BASH doesn't know $ref any longer";

fi

read -s -N 1 -p "Press any key to continue...";
echo "";

ここで明確にするために、関数はリテラル テキストをテストします。コマンドがBashで呼び出されるたびに、変数は通常、次の場合を除き、基になる値で「スワップアウト」または「置換」されます。

  • $varRef ($) はエスケープされます: $varRef
  • $varRef は単一引用符で囲まれた '$varRef' です
于 2011-05-15T02:09:05.323 に答える
1

何が必要なのか正確にはわかりません。それにもかかわらず、私はあなたに返信しようとしています。

つまり、テストが失敗した場合は終了する必要があります。

コード:

${varName:?    "${varName} is not defined"}

「varName」という名前の変数がない場合、ゼロ以外の終了コードを返します。最後のコマンドの終了コードは に保存され$?ます。

コードについて:

val=${1:?    "${1}    must be defined, preferably in $basedir"}

多分それはあなたが必要とすることをしていません。$1が定義されていない場合、は"${1}"何も置き換えられません。${1}おそらく、置換なしで文字通り書く一重引用符を使用したいと思うでしょう。

val=${1:?    '${1}    must be defined, preferably in $basedir'
于 2009-05-17T12:02:35.257 に答える
1

これがまさにあなたが望むものかどうかはわかりませんが、新しい複雑なスクリプトを書くときに私が使用する便利なトリックは、「set -o」を使用することです

set -o #は、未設定の変数が見つかったときにスクリプトを爆発させます

例えば:

$ grep '$1' chex.sh

ケース「$1」

$ ./chex.sh

./chex.sh: 111 行目: $1: バインドされていない変数

$ ./chex.sh フー

正しくない/オプションが渡されませんでした..終了します

于 2010-11-06T00:54:14.540 に答える
0
if set | grep -q '^VARIABLE='
then
    echo VARIABLE is set
fi
于 2014-06-01T07:40:27.903 に答える