web-dev-qa-db-ja.com

変数が空であるか、スペースのみが含まれているかどうかをテストするにはどうすればよいですか?

次のbash構文は、paramが空でないかどうかを確認します。

 [[ !  -z  $param  ]]

例えば:

param=""
[[ !  -z  $param  ]] && echo "I am not zero"

出力なしとその罰金。

ただし、paramが1つ(または複数)の空白文字を除いて空の場合、大文字と小文字は異なります。

param=" " # one space
[[ !  -z  $param  ]] && echo "I am not zero"

「ゼロではない」が出力されます。

空白文字のみを含む変数を空と見なすようにテストを変更するにはどうすればよいですか?

261
maihabunash

最初に、 -z test は明示的に次のようになっていることに注意してください:

文字列の長さがゼロです

つまり、スペースのみを含む文字列は、長さがゼロでないため、-zの下ではnotである必要があります。

パターン置換パラメーター展開 を使用して、変数からスペースを削除する必要があります。

[[ -z "${param// }" ]]

これはparam変数を展開し、パターン(単一のスペース)のすべての一致を何も置換しないため、スペースのみを含む文字列は空の文字列に展開されます。


それがどのように機能するかについての非常に正確 は、${var/pattern/string}patternの最初の最長一致をstringで置き換えることです。 (上記のように)pattern/で始まる場合、all一致を置き換えます。置換は空なので、最後の/stringの値を省略できます。

$ {parameter/pattern/string}

patternは、ファイル名展開と同じように展開されてパターンを生成します。 Parameterが展開され、その値に対するpatternの最長一致がstringpatternが「/」で始まる場合、patternのすべての一致はstring。通常、最初に一致したものだけが置き換えられます。 ...stringがnullの場合、patternの一致は削除され、/に続くpatternは省略できます。

結局、すべてのスペースを削除するために${param// }を使用します。

ksh(元の場所)、zshbashには存在しますが、その構文はPOSIXではないため、shスクリプトでは使用しないでください。

304
Michael Homer

文字列に承認されたセットの文字のみが含まれていることを確認する簡単な方法は、不正な文字の存在をテストすることです。したがって、文字列にスペースのみが含まれているかどうかをテストする代わりに、文字列にスペース以外の文字が含まれているかどうかをテストします。 bash、kshまたはzshの場合:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

「スペースのみで構成される」には、空の(または未設定の)変数の場合が含まれます。

空白文字をテストしたい場合があります。 [[ $param = *[^[:space:]]* ]]を使用して、ロケール設定、またはテストする空白文字の明示的なリストを使用します。 [[ $param = *[$' \t\n']* ]]スペース、タブ、または改行をテストします。

=内の[[ … ]]を使用したパターンと文字列の照合はksh拡張です(bashとzshにも存在します)。すべてのBourne/POSIXスタイルで、case構文を使用して、文字列をパターンと照合できます。標準のシェルパターンは、ほとんどの正規表現構文のように!ではなく^を使用して文字セットを否定することに注意してください。

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

空白文字をテストするために、$'…'構文はksh/bash/zshに固有です。これらの文字をスクリプトに文字通り挿入するか(バックスラッシュ+改行が何もないため、改行は引用符で囲む必要があることに注意してください)、または生成することができます。

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac

POSIXly:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

空白非空白未設定を区別するには:

case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:]は、水平方向のスペース文字用です(ASCIIのスペースとタブですが、ロケールによってはさらに多くある可能性があります。システムによっては、改行しないスペース(利用可能な場合)が含まれているものと含まれていないものがあります)。垂直方向のスペース文字も(改行や改ページなど)必要な場合は、[:blank:][:space:]に置き換えます。

22

goodスクリプト言語のスクリプトではなく、シェルスクリプトを記述する唯一の理由は、極端な移植性が最優先事項である場合ですレガシー/bin/shはあなたが持っていると確信できる唯一のものですが、たとえばPerlはmoreが利用可能である可能性が高いですBashよりもクロスプラットフォーム。したがって、本当に普遍的ではない機能を使用するシェルスクリプトを作成しないでください-いくつかの独自のUnixベンダーがシェル環境POSIX.1-2001より前。

このテストを行うポータブルな方法がありますが、trを使用する必要があります。

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]

$IFSのデフォルト値は、スペース、タブ、および改行です。)

printfビルトイン自体は移植性に優れていますが、これに依存することで、echoのバリアントを特定するよりもはるかに簡単です。)

5
zwol
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi
5
Guru

投稿したコード[[ ! -z $param ]] && echo "I am not zero"は、paramが未設定/未定義または空の場合(bash、ksh、zshの場合)I am not zeroを出力します。

または印刷するには、paramにスペースのみが含まれている場合(スペースを削除する)、POSIXly(より広い範囲のシェルの場合):

 [   -z "${param#"${param%%[! ]*}"}"   ] && echo "empty"

説明:

  • ${param# … }リーディングテキストを削除します。
  • その先頭のテキストは次のように提供されます:${param%%[! ]*}
  • 前のすべてのスペース任意の非スペース文字、つまりすべての先行スペースに展開されます。

全体の展開の最終結果は、すべての先行スペースが削除されることです。

この拡張結果は、長さが0かどうかがテストされます。

  • 結果が空の場合、変数は空でした、または
  • 先頭のスペースを削除すると、空白になります。

したがって、テストが真の場合、変数はすでに空であるか、内部にスペースしかありませんでした。


このコンセプトは、より多くの文字タイプに拡張するのは簡単です。タブも含めるには、ブラケット式の中に明示的なタブを配置します。

 [ -z "${param#"${param%%[!     ]*}"}" ] && echo "empty"

または、削除する必要がある文字を含む変数を使用します。

 var=$' \t'                                    # in ksh, bash, zsh
 [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"

または、POSIXの「文字クラス式」を使用できます(空白はスペースとタブを意味します)。

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
1
Isaac

変数が空であるか、スペースが含まれているかどうかをテストするには、次のコードを使用することもできます。

${name:?variable is empty}
1
pratik