it-swarm.cn

如何测试变量是否为空或仅包含空格?

以下bash语法验证param是否为空:

 [[ !  -z  $param  ]]

例如:

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

没有输出,它的罚款。

但是,当param为空(除了一个(或多个)空格字符之外)时,情况有所不同:

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

输出“我不为零”。

如何更改测试以将仅包含空格字符的变量视为空?

261
maihabunash

首先,请注意 -z test 明确适用于:

字符串的长度为零

也就是说,仅包含空格的字符串在-z下应该为not为true,因为它的长度为非零。

您想要的是使用 样式替换参数扩展 从变量中删除空格:

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

这将扩展param变量,并且不使用任何内容替换模式的所有匹配项(单个空格),因此仅包含空格的字符串将被扩展为空字符串。


工作原理的坚韧不拔${var/pattern/string}pattern的第一个最长匹配替换为string。当pattern/开头(如上所述)时,它将替换all匹配项。由于替换为空,因此我们可以省略最后的/string值:

$ {参数/模式/字符串}

就像文件名扩展一样,pattern被扩展以生成模式。 参数被扩展,并且pattern与其值的最长匹配被替换为string。如果pattern以“ /”开头,则pattern的所有匹配项都将以string替换。通常只替换第一场比赛。 ...如果字符串为空,则删除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构造将字符串与模式进行匹配。请注意,标准Shell模式使用!来否定字符集,而不是像大多数正则表达式语法一样使用^

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
32

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
Stéphane Chazelas

编写Shell脚本而不是使用good脚本语言编写脚本的唯一剩余原因是,极端的可移植性是否是首要考虑因素。遗留的/bin/sh是您唯一可以确定的东西,但是Perl例如more可能比Bash可以跨平台使用。因此,切勿编写使用非真正通用功能的Shell脚本,并切记一些专有的Unix供应商冻结了他们的Shell环境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"将打印I am not zero如果参数未设置/未定义或为空(在bash,ksh和zsh中)。

如果参数仅包含空格(删除空格),则以POSIXly(对于更大范围的shell)打印

 [   -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