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

mai*_*ash 290 shell bash string shell-script

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

 [[ !  -z  $param  ]]
Run Code Online (Sandbox Code Playgroud)

例如:

param=""
[[ !  -z  $param  ]] && echo "I am not zero"
Run Code Online (Sandbox Code Playgroud)

没有输出,很好。

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

param=" " # one space
[[ !  -z  $param  ]] && echo "I am not zero"
Run Code Online (Sandbox Code Playgroud)

“我不是零”是输出。

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

Mic*_*mer 346

首先,请注意该-z测试明确用于:

字符串的长度为零

也就是说,只包含空格的字符串应该不会是真的下-z,因为它有一个非零长度。

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

[[ -z "${param// }" ]]
Run Code Online (Sandbox Code Playgroud)

这将扩展param变量并将模式的所有匹配项(单个空格)替换为空,因此其中只有空格的字符串将被扩展为空字符串。


工作原理本质${var/pattern/string}替换patternwith的第一个最长匹配string。当pattern/(如上)开头时,它将替换所有匹配项。因为替换为空,我们可以省略final/stringvalue:

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

图案被膨胀,以产生一个模式,就像在文件名扩展。参数被扩展,模式与其值的最长匹配被替换为string。如果模式以“/”开始,所有的比赛模式被替换为的字符串。通常只替换第一个匹配项。... 如果string为 null,则删除模式的匹配项,并且可以省略/ 后面的模式

毕竟,我们最终${param// }删除了所有空格。

请注意,尽管存在于ksh(起源地), zshand bash,但该语法不是POSIX,不应在sh脚本中使用。

  • @MichaelHomer 答案 `[[ -z "${param// }" ]]` 确实看起来像 `pattern` 是空的,而 `replacement string` 是一个空格。啊!我现在看到了`如果模式以斜线开头`我错过了那部分。所以模式是`/`,字符串被留下,因此是空的。谢谢。 (7认同)
  • 唔。如果它是 `${var/pattern/string}` 那么它不应该是 `[[ -z ${param/} ]]` 斜杠之间的空格作为模式,后面没有任何内容作为字符串? (5认同)
  • 使用他们说的‘sed’……只是‘echo’他们说的变量…… (3认同)

Gil*_*il' 34

检查字符串是否仅包含授权集中的字符的简单方法是测试是否存在未授权字符。因此,不是测试字符串是否只包含空格,而是测试字符串是否包含空格以外的某些字符。在 bash、ksh 或 zsh 中:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi
Run Code Online (Sandbox Code Playgroud)

“仅由空格组成”包括空(或未设置)变量的情况。

您可能想要测试任何空白字符。使用[[ $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
Run Code Online (Sandbox Code Playgroud)

要测试空白字符,$'…'语法特定于 ksh/bash/zsh;您可以按字面意思在脚本中插入这些字符(请注意,换行符必须在引号内,因为反斜杠+换行符扩展为空),或者生成它们,例如

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


Sté*_*las 23

POSIXly:

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

区分空白非空白、未设置

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

[:blank:]用于水平间距字符(ASCII 中的空格和制表符,但您的语言环境中可能还有一些;有些系统将包括不间断空格(如果可用),有些则不会)。如果您还需要垂直间距字符(如换行符或换页符),请替换[:blank:][:space:].


zwo*_*wol 6

编写一个 shell 脚本而不是一个好的脚本语言的脚本的唯一剩下的原因是,如果极端的可移植性是一个压倒一切的问题。 遗产/bin/sh是您唯一可以确定的东西,但例如 Perl比 Bash更有可能跨平台使用。因此,永远不要编写使用并非真正通用的特性的 shell 脚本——并记住,在 POSIX.1-2001 之前,一些专有的 Unix 供应商冻结了他们的 shell 环境。

有一种便携式方法可以进行此测试,但您必须使用tr

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]
Run Code Online (Sandbox Code Playgroud)

$IFS方便地,的默认值是一个空格、一个制表符和一个换行符。)

printf内置函数本身是可移植的,但依赖它比找出echo你有哪个变体要容易得多。)


小智 5

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
Run Code Online (Sandbox Code Playgroud)