bash:测试是否设置了 $WORD

Mar*_*ter 80 bash shell-script

我正在寻找一个构造 in bash,以确定变量$WORD是否是定义的词之一。我需要这样的东西:

if "$WORD" in dog cat horse ; then 
    echo yes
else
    echo no
fi
Run Code Online (Sandbox Code Playgroud)

bash 有这样的结构吗?如果不是,最接近的会是什么?

Joh*_*man 101

case $word in
    dog|cat|horse) echo yes;;
    *)             echo no;;
esac
Run Code Online (Sandbox Code Playgroud)


Jos*_* R. 91

这是使用正则表达式的 Bash-only (>= version 3) 解决方案:

if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then
    echo "$WORD is in the list"
else
    echo "$WORD is not in the list"
fi
Run Code Online (Sandbox Code Playgroud)

如果您的单词列表很长,您可以将其存储在一个文件中(每行一个单词)并执行以下操作:

if [[ "$WORD" =~ $(echo ^\($(paste -sd'|' /your/file)\)$) ]]; then
    echo "$WORD is in the list"
else
    echo "$WORD is not in the list"
fi
Run Code Online (Sandbox Code Playgroud)

文件方法的一个警告:

感谢@terdon 提醒我用^和正确锚定模式$。

  • 如果您希望搜索不区分大小写,`shopt -s nocasematch` 可能会有所帮助。 (2认同)

ter*_*don 13

怎么样:

#!/usr/bin/env bash

WORD="$1"
for w in dog cat horse
do
  if [ "$w" == "$WORD" ] 
  then
      yes=1
      break
  fi
done;
[ "$yes" == "1" ] && echo "$WORD is in the list" || 
                     echo "$WORD is not in the list"
Run Code Online (Sandbox Code Playgroud)

然后:

$ a.sh cat
cat is in the list
$ a.sh bob
bob is not in the list
Run Code Online (Sandbox Code Playgroud)


Bin*_*rus 6

我刚刚遇到了同样的问题,并找到了一个令人惊讶的易于理解的解决方案,不需要任何正则表达式知识。

这适用于 Bash 和 ksh,以及 zsh 中setopt kshglob:

WORD=abc
[[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set.
Run Code Online (Sandbox Code Playgroud)

(本机 zsh 版本在没有符号的情况下是相同的@)。

这是如何运作的?我不想在这里重复 bash 手册的大部分内容,但用我自己的话来说:

如果二元运算符==与复合命令一起使用[[,则运算符右侧的单词将进行模式匹配,如 bash 手册中“模式匹配”部分所述。extglob此外,在这些条件下,在匹配时,假定已设置shell 选项(无论实际设置如何);这是理解上述内容的关键点。

但是,如果您的集合中的单词已经包含在模式匹配、命令替换和其他扩展中具有特殊含义的字符,该怎么办?补救措施很简单:只需使用类似的东西

[[ "$WORD" == @('a*'|abc|'?ghi'|'$DontExpandMe'|barbaz) ]] && echo Word is in set.
Run Code Online (Sandbox Code Playgroud)

我发现这是一个非常简单、易于理解和高效(只要$WORD短)的解决方案,它没有副作用,也没有像set基于 的方法那样危险。