【问题标题】:How do I compare two strings in if condition in bash如何比较bash中if条件中的两个字符串
【发布时间】:2013-12-23 11:20:40
【问题描述】:
s="STP=20"

if [[ "$x" == *"$s"* ]]

if 条件始终为假;为什么?

【问题讨论】:

  • $x 的值是多少?
  • if 语句之前尝试echo "$x"。这行代码将按预期工作。
  • 谢谢。我的 x 变量由 awk x=$(awk '{printf "%s ", $17}' this) 分配 – Sanchai_28 35 秒前编辑
  • 你能不能 echo "$x" | cat -vte 告诉我们输出结果。
  • 密切相关的问题:SO 20742474SO 20780315SO 20780890SO 20781258。不是完全重复,而是相同的数据流。

标签: bash if-statement


【解决方案1】:

试试这个:http://tldp.org/LDP/abs/html/comparison-ops.html

string comparison

=

  is equal to

  if [ "$a" = "$b" ]

【讨论】:

  • 谢谢。我的 x 变量由 awk x=$(awk '{printf "%s ", $17}' this) 分配
  • 我记得== 也适用于比较,=== 之间没有区别..
  • 如果你使用[ ]会有区别(你不应该这样做,请首选[[ ]])。 ===[[ ]] 条件下的工作方式完全相同,但只有 =[ ] 中可用。请参阅thisthis 了解更多信息。
【解决方案2】:

[ ... ][[ ... ]] 之间的相等性测试存在差异。

[ ... ]test 命令的别名:

STRING1 = STRING2 字符串相等

但是,当使用[[ ... ]]

当使用==!= 运算符时,运算符右侧的字符串被视为一个模式,并根据下面模式匹配中描述的规则进行匹配。如果启用了 shell 选项 nocasematch,则执行匹配时不考虑字母字符的大小写。如果字符串匹配 (==) 或不匹配 (!=) 模式,则返回值为 0,否则为 1。可以引用模式的任何部分以强制将其作为字符串匹配。

= 符号似乎也是如此:

$ foo=bar
$ if [[ $foo = *ar ]]
> then
>     echo "These patterns match"
> else
>     echo "These two strings aren't equal"
> fi
These patterns match

注意区别:

$ foo=bar
> if [ $foo = *ar ]
> then
>     echo "These patterns match"
> else
>     echo "These two strings aren't equal"
> fi
These two strings aren't equal

但是,[ $f00 = *ar ] 语法存在一些陷阱。这与以下内容相同:

test $foo = *ar

这意味着 shell 将在执行语句之前插入 glob 表达式和变量。如果$foo 为空,则命令将变为:

test = *ar  # or [ = *ar ]

由于= 不是test 中的有效比较运算符,您将收到如下错误:

bash: [: =: unary operator expected

这意味着[ 期望在test 手册页中找到一个参数。

而且,如果我的目录中碰巧有一个文件bar,shell 会将*ar 替换为与该模式匹配的所有文件(在本例中为bar),因此命令将变为:

[ $foo = bar ]

这是真的。

要解决[ ... ] 的各种问题,您应该始终在参数周围加上引号。这将防止 shell 对 glob 进行插值,并有助于处理没有值的变量:

[ "$foo" = "*ar" ]

这将测试变量$foo 是否等于字符串*ar。即使$foo 为空,它也会起作用,因为引号将强制进行空字符串比较。 *ar 周围的引号将阻止 shell 插入 glob。这是一个真正的平等。

当然,如果你在使用[[ ... ]]时使用引号,你也会强制匹配字符串:

foo=bar
if [[ $foo == "*ar" ]]
then
    echo "This is a pattern match"
else
    echo "These strings don't match"
fi

所以,最后,如果你想测试字符串是否相等,你可以使用[ ... ][[ ... ]],但你必须引用你的参数。如果要进行 glob 模式匹配,则必须去掉引号,并使用 [[ ... ]]

【讨论】:

    【解决方案3】:

    要比较变量 xy 中的两个字符串是否相等,请使用

    if test "$x" = "$y"; then
       printf '%s\n' "equal"
    else
       printf '%s\n' "not equal"
    fi
    

    要测试x 是否出现在y 的某处,请使用

    case $y in
       (*"$x"*)
          printf '%s\n' "$y contains $x"
          ;;
       (*)
          printf '%s\n' "$y does not contain $x"
          ;;
    esac
    

    请注意,这些结构可以移植到任何 POSIX shell,而不仅仅是 bash。用于测试的 [[ ]] 构造(还不是)标准的 shell 功能。

    【讨论】:

      【解决方案4】:

      我不知道你在哪里想出了*,但你真的很接近:

      s="STP=20"
      if [[ "STP=20" == "$s" ]]; then
          echo "It worked!"
      fi
      

      【讨论】:

      • bash 允许在 [[ 内进行模式匹配,因此如果 $x 包含 $s 作为子字符串,则原始 OP 的代码应评估为 true。
      【解决方案5】:

      您需要在字符串s="STP=20" 中使用\ 转义=

      s="STP\=20"
      
      if [[ "STP\=20" == "$s" ]]; then echo Hi; else echo Bye; fi
      

      【讨论】:

      • s="STP=20" && if [[ "STP=20" == "$s" ]]; then echo Hi; else echo Bye; fi 也给出了Hi
      • @Sanchai_28 我很高兴!
      猜你喜欢
      • 2015-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      • 2016-12-12
      • 2021-10-14
      相关资源
      最近更新 更多