【问题标题】:Test if string has non whitespace characters in Bash测试字符串在 Bash 中是否有非空白字符
【发布时间】:2012-04-03 18:56:32
【问题描述】:

我的脚本正在读取和显示 id3 标签。如果该字段为空白,我试图让它回显未知,但我尝试的每个 if 语句都不起作用。 id3 标记是固定大小的,因此它们永远不会为空,但如果没有值,它们将被空白填充。即标题标签的长度为 30 个字符。到目前为止我已经尝试过

echo :$string: #outputs spaces between the 2 ::

if [ -z "$string" ] #because of white space will always evaluate to true

x=echo $string | tr -d ' '; if [ -z "$string" ]; #still 评估为 true 但回显 :$x: 它回显 ::

脚本

#!bin/bash
echo "$# files";
while [ "$i" != "" ];
do
   TAG=`tail -c 128 "$i" | head -c 3`;
   if [ $TAG="TAG" ]
   then
      ID3[0]=`tail -c 125 "$1" | head -c 30`;
      ID3[1]=`tail -c 95 "$1" | head -c 30`;
      ID3[2]=`tail -c 65 "$1" | head -c 30`;
      ID3[3]=`tail -c 35 "$1" | head 4`;
      ID3[4]=`tail -c 31 "$i" | head -c 28`;
      for i in "${ID3[@]}"
      do
         if [ "$(echo $i)" ] #the if statement mentioned
         then
            echo "N/A";
         else
            echo ":$i:";
         fi
      done
   else
      echo "$i does not have a proper id3 tag";
   fi
   shift;
done

【问题讨论】:

  • Michal Politowski: -z 表示操作数的长度为零
  • @Peter.O: 是的,$x 是应该测试的字符串,而不是 $string。
  • 是的,在我上传脚本之前,我以 $string 为例; $i 是字符串,它是数组中的一个值。我的循环可能有问题吗?
  • 您还必须将if [ $TAG="TAG" ] 更改为if [ "$TAG" = "TAG" ] - 第一个版本仅向[ 命令发送一个非空参数,因此它始终返回true。
  • @yamikoWebs 除了 glenn jackman 的 评论之外,您还混淆了您的 $1 和 $i,以及 head 4 (?) head -c 4 ...解决了这些问题,并且您选择了 if 语句,脚本就可以工作了 :)

标签: linux string bash if-statement comparison


【解决方案1】:

其中许多答案比应有的复杂得多,或者可读性差得多。

[[ $string = *[[:space:]]* ]]  && echo "String contains whitespace"
[[ $string = *[![:space:]]* ]] && echo "String contains non-whitespace"

【讨论】:

  • 这并没有回答这个问题。 OP 的问题是如何测试一个字符串是否至少包含一个非空格。这是对至少包含一个空格的字符串的测试。
  • @kkm,我很尴尬错误存活了这么久。已解决。
  • @CharlesDuffy:谢谢!不知道! 模式否定。很酷的 bashism!
  • @kkm,不是 bashism——这是 POSIX fnmatch 行为,因此它适用于符合标准的 shell globbing 表达式。见pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • ...虽然,是的,[[ ]] 本身当然是一种 bashism(好吧,一个被盗/采用的 ksh-ism)。 :)
【解决方案2】:

您可以使用 bash 的正则表达式语法。

它要求您使用双方括号[[ ... ]],(通常更通用)。
该变量不需要被引用。正则表达式本身不得被引用

for str in "         "  "abc      " "" ;do
    if [[ $str =~ ^\ +$ ]] ;then 
      echo -e "Has length, and contain only whitespace  \"$str\"" 
    else 
      echo -e "Is either null or contain non-whitespace \"$str\" "
    fi
done

输出

Has length, and contain only whitespace  "         "
Is either null or contain non-whitespace "abc      " 
Is either null or contain non-whitespace "" 

【讨论】:

  • 一切都与所有空白相呼应
  • 感谢 yamikoWebs ...我开始使用正则表达式,然后选择通配符...我已恢复为正则表达式...编辑答案以使用 bash 的正则表达式。
  • 正如目前所写的那样,它只检查空格,而不是所有空白字符——它不处理制表符、换行符等等。
  • ...另外,echo -e 在这里几乎肯定是错误的——如果您想显示不可打印的字符并逐字呈现转义序列,更合适的工具可能是:@987654325 @
  • ...但使用 echo -e 意味着您将转义序列渲染为它们所代表的文字字符,这使得 远离 向用户准确显示正在处理的数据不是更接近它(如果数据包含文字反斜杠后跟n,他们为什么希望以与 文字 换行符无法区分的方式查看它?)
【解决方案3】:

一种非 bash 特定的、仅限 shell 的变体:

case "$string" in
 *[!\ ]*) echo "known";;
 *) echo "unknown";;
esac

【讨论】:

  • 最好使用 POSIX 字符类 [[:space:]] 而不是专门列出 \ 。
【解决方案4】:
[[ -z `echo $string` ]]

反引号在其中执行命令; bash 行解析将制表符和换行符转换为空格并连接双空格。 echo 命令重新发出此字符串,该字符串被 [[ ]] 收缩为空字符串以进行最终测试。我认为这是通过以下最短解决方案:

> VAR="$(echo -e " \n\t")"
> [[ -z  `echo $VAR` ]] ; echo $?
0
> VAR="$(echo -e " \na\t")"
> [[ -z  `echo $VAR` ]] ; echo $?
1
> VAR="$(echo -e "aaa bbb")"
> [[ -z  `echo $VAR` ]] ; echo $?
1
> VAR=
> [[ -z  `echo $VAR` ]] ; echo $?
0

【讨论】:

    【解决方案5】:

    启用扩展 glob (shopt -s extglob):

    if [ -n "${string##+([[:space:]])}" ]; then
        echo '$string has non-whitespace characters'
    fi
    

    【讨论】:

    • 它提出了太多的参数和预期的二元运算符
    • 它们都回响,包括我怀疑有空格的那些。有没有办法可以验证它们是空格而不是其他东西?
    【解决方案6】:
    if [ "$(echo "$string" | tr -s ' ')" == " " ]; then
      echo "all white space"
    fi
    

    这会将所有重复的空格压缩为一个空格,然后进行比较。

    【讨论】:

    • 我循环遍历所有标签,但并非所有标签都是 30 个字符,是否有另一种方法可以测试字符串是否都是空格?
    • 标签之间是否有空格?
    • 是的。如果标签是 10 个字符,则其余部分用空格填充。
    • 你的例子对我来说总是评估为假
    • 好的,我以为我测试过了。你的意见究竟是什么?
    【解决方案7】:

    这一项检查零长度或空格或制表符

    S="Something"
    if [[ "x$S" == "x" || "x$S" == x*\ * || "x$S" == x*\    * ]] ;then
      echo "Is not OK"
    else
      echo "Is OK"
    fi
    

    【讨论】:

      【解决方案8】:

      分享一种更便携的方法,不需要双括号 [[ ]],同时尽可能保持简单。

      检测仅包含空格或 = null 的字符串:

      if [ -z "${string// }" ]; then <do something>; fi
      

      在这种情况下是:

      ${var// }
      

      如:

      if [ -z "${string// }" ]; then echo "It's empty!"; fi
      

      这只是通过替换将所有空格替换为 null。如果 $string 仅包含空格,则 -z 测试将评估为 TRUE。如果字符串中有非空白字符,则等式的计算结果为 FALSE。

      进一步详细说明 BASH(因为 OP 在 BASH 中询问了这一点),上面的示例不会捕获标签,尽管可以这样做。以下是 BASH 中的更多示例,它们按预期工作和不按预期工作。

      假设搜索字符串中有一个标签。

      这行得通:

      string=$(echo -e "\t"); if [ -z ${string// } ]; then echo "It's empty!"; fi
      

      但这些不是:

      string=$(echo -e "\t"); if [ -z "${string// }" ]; then echo "It's empty!"; fi
      string=$(echo -e "\t"); if [ -z '${string// }' ]; then echo "It's empty!"; fi
      

      上面最后两个示例都报告字符串不为空。如果您认为制表符是空白,那将是一个问题,您应该使用第一个示例。

      换行符呢?让我们看一下\n 场景。首先,“正确”的行为取决于您的期望。

      这些将换行符 (\n) 视为空格(等式评估为 TRUE):

      string=$(echo -e "\n\n"); if [ -z ${string// } ]; then echo "It's empty!"; fi
      string=$(echo -e "\n\n"); if [ -z "${string// }" ]; then echo "It's empty!"; fi
      

      这不是(等式计算结果为 FALSE),这意味着这个等式认为换行符不是空格。

      string=$(echo -e "\n\n"); if [ -z '${string// }' ]; then echo "It's empty!"; fi
      

      如果您需要检查换行符、制表符和空格,您可能需要使用两个 IF/THEN 语句或上述 CASE 方法。

      【讨论】:

      • 这行得通,${var// } 究竟代表什么?是不是要换东西了?
      • 是的。它用 null 代替空格字符(又名“空白”)。
      猜你喜欢
      • 2012-04-25
      • 2018-08-10
      • 1970-01-01
      • 2015-06-18
      • 2015-11-12
      • 1970-01-01
      相关资源
      最近更新 更多