参照された変数がnullの場合、どのようにnullに拡張できますか?

参照された変数がnullの場合、どのようにnullに拡張できますか?

実行中のスクリプトがあるとしましょう。

some-command "$var1" "$var2" ...

空の場合は、空のvar1文字列ではなく空の文字列に置き換えて、実行されるコマンドを次のようにします。

some-command "$var2" ...

いいえ:

some-command '' "$var2" ...

変数をテストして条件付きで含めるよりも簡単な方法はありますか?

if [ -n "$1" ]; then
    some-command "$var1" "$var2" ...
    # or some variant using arrays to build the command
    # args+=("$var1")
else
    some-command "$var2" ...
fi

bash、zshなどからnullに拡張されるパラメータ置換はありますか?それでも残りのパラメータにワイルドカードを使用したい場合があるため、これを無効にして変数を逆参照することはオプションではありません。

答え1

Posix互換シェルそして大きな打撃を受けました ${parameter:+word}:

もし範囲設定されていないか null です。それ以外の場合はnullに置き換える必要があります。言葉(または空の文字列の場合言葉省略)を交換する必要があります。

だからあなたはこれを行うことができます:

${var1:+"$var1"}

設定されていて空でない場合はvar1確認され、使用されます(通常の二重引用符ルールを使用)。"$var1"そうでなければ、何も膨らませないでしょう。参考にしてください内部にここに引用された内容は全体ではなく一部です。

zshでも動作します。変数を繰り返す必要があるため、理想的ではありませんが、正確に目的の結果が得られます。

set-but-empty変数を空のパラメータに拡張するには、代わりにset-but-emptyを使用します${var1+"$var1"}

答え2

zsh引用符を省略すると、デフォルトでは次のことが発生します。

some-command $var1 $var2

実際にzshのパラメータ拡張に引用文がまだ必要な唯一の理由は、この動作(null削除)を避けるためですzshパラメータ拡張を引用しないときに他のシェルに影響を与えるその他の問題(暗黙の分割+glob)

分割とglobが無効になっている場合は、他のPOSIX様シェルでも同じことができます。

(IFS=; set -o noglob; some-command $var1 $var2)

変数が0または1の値を持つことができる場合は、スカラー変数の代わりに配列でなければならず、次のように使用する必要があると思います。

some-command "${var1[@]}" "${var2[@]}"

値を含めるvar1=(value)とき、null 値を含めるとき、含めるときを使用します。var1var1=('')var1=()いいえ値。

答え3

-nスイッチドライランの有無にかかわらず、コマンドを実行するbashスクリプトでrsyncを使用してこの問題が発生しました。 rsyncと多くのgnuコマンドは、それを''有効な最初の引数として受け入れ、存在しないときとは異なる動作をすることがわかりました。

空のパラメータがほとんど完全に見えないため、デバッグにはかなり長い時間がかかりました。

rsyncリストの誰かが私にこの問題を回避する方法を示しました。非常にコーディングを簡素化します。私が正しく理解したなら、これは@Stéphane Chazelasが最後に提案したバリエーションです。

多くの個々の変数にコマンド引数を設定します。これは問題に適した順序または論理に設定できます。

次に、最後に変数を使用して、すべてが正しい位置にある配列を構築し、それを実際のコマンドの引数として使用します。

このようにして、コマンドはパラメータの各バリエーションに対して繰り返されず、コードの1つの場所でのみ実行されます。

この方法を使用すると、空の変数はすべて消えます。

私はevalを使用することが眉をひっくり返すことを知っています。すべての詳細を覚えているわけではありませんが、この方法で作業するには、空白を含むパラメータの処理に関する作業が必要なようです。

例:

dry_run=''
if [[ it is a test run ]]
then
  dry_run='-n'
fi
...
rsync_options=(
  ${dry_run}
  -avushi
  ${delete}
  ${excludes}
  --stats
  --progress
)
...
eval rsync "${rsync_options[@]}" ...

関連情報