bash字符串与多个正确值进行比较

eag*_*789 46 string bash comparison compare

我有以下的bashscript:

function get_cms {
    echo "input cms name"
    read cms
    cms=${cms,,}
    if [ "$cms" != "wordpress" && "$cms" != "meganto" && "$cms" != "typo3" ]; then
        get_cms
    fi
}
Run Code Online (Sandbox Code Playgroud)

但无论我输入什么(正确和不正确的值),它都不会再次调用该函数,因为我只想允许这3个输入中的1个.我用||尝试过 [var!= value]或[var!= value1]或[var!= value1]但没有任何效果.有人能指出我正确的方向吗?

小智 68

如果主要目的是检查列表中是否找不到提供的值,也许您可​​以通过"等号"运算符使用BASH内置的扩展正则表达式匹配(另请参阅此答案):

if ! [[ "$cms" =~ ^(wordpress|meganto|typo3)$ ]]; then get_cms ; fi
Run Code Online (Sandbox Code Playgroud)

祝你今天愉快

  • 更干净的答案加分。我更喜欢把 ! 在 [[ ]] 之内,但两者同样有效。 (3认同)

Alf*_*lfe 41

也许你应该更好地使用a case这样的列表:

case "$cms" in
  wordpress|meganto|typo3)
    do_your_else_case
    ;;
  *)
    do_your_then_case
    ;;
esac
Run Code Online (Sandbox Code Playgroud)

我想很久这样的列表这个更好的可读性.

如果您仍然喜欢,if可以通过两种方式使用单支架:

if [ "$cms" != wordpress -a "$cms" != meganto -a "$cms" != typo3 ]; then
Run Code Online (Sandbox Code Playgroud)

要么

if [ "$cms" != wordpress ] && [ "$cms" != meganto ] && [ "$cms" != typo3 ]; then
Run Code Online (Sandbox Code Playgroud)

  • OP 正在使用 ≠ (`!=`) 来制定他的原始条件;我的版本与 `case` 匹配(所以它更像是使用与 `=` 的比较),因此是倒置。 (2认同)
  • @Alfe,请参阅http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html中的`[OB XSI]符号.如果单击它,它会将您链接到一个定义:*所描述的功能可能会在本卷POSIX.1-2008的未来版本中删除.严格遵守POSIX应用程序和严格遵守XSI应用程序不得使用过时功能*.我怀疑GNU coreutils或bash实际上会删除它,但它*将被安排在将来不再是POSIX规定的行为(出于好的原因,考虑到引入的歧义). (2认同)

dev*_*ull 39

而不是说:

if [ "$cms" != "wordpress" && "$cms" != "meganto" && "$cms" != "typo3" ]; then
Run Code Online (Sandbox Code Playgroud)

说:

if [[ "$cms" != "wordpress" && "$cms" != "meganto" && "$cms" != "typo3" ]]; then
Run Code Online (Sandbox Code Playgroud)

您可能还想参考Conditional Constructs.

  • 一遍又一遍地重复 `"$cms" !=` 并不是很干燥。它在任何情况下都为拼写错误留下了空间(例如 `"$csm" !=`),并且您没有编译器在 shell 中向您指出这一点。最好尽量避免重复变量名。(有关实现此目的的方法,请参阅我的答案。) (2认同)

stu*_*eek 11

正如@Renich 所建议的那样(但不幸的是,有一个重要的错字尚未修复),您还可以使用扩展的通配符进行模式匹配。因此,您可以ls *.pdf在 bash 比较中使用用于匹配命令参数(例如)中的文件的相同模式。

对于您的特定情况,您可以执行以下操作。

if [[ "${cms}" != @(wordpress|magento|typo3) ]]
Run Code Online (Sandbox Code Playgroud)

@意思是“匹配给定的模式之一”。所以这基本上cms说不等于'wordpress' OR 'magento' OR 'typo3'。在正常的正则表达式语法中,@ 类似于^(wordpress|magento|typo3)$.

Mitch Frazier 在 Linux Journal 上有两篇关于Bash 中的模式匹配Bash Extended Globbing 的好文章。

有关扩展通配符的更多背景信息,请参阅模式匹配(Bash 参考手册)


Ren*_*ich 5

这是我的解决方案

if [[ "${cms}" != @(wordpress|magento|typo3) ]]; then
Run Code Online (Sandbox Code Playgroud)

  • 在你的 extglob 中不是 `+` 而是 `@`。否则你会得到错误的结果,例如`wordpressmagento` 或`typo3typo3`。 (7认同)