【问题标题】:Bash string comparisonBash 字符串比较
【发布时间】:2015-08-30 16:41:05
【问题描述】:

我正在尝试比较 Bash 脚本中的两个字符串,但得到了非常奇怪的结果。

if [[ "010" < "01." ]]; then echo "Wrong"; else echo "OK"; fi
if [[ "010" < "01.0" ]]; then echo "Wrong"; else echo "OK"; fi
if [ "010" \< "01." ]; then echo "Wrong"; else echo "OK"; fi
if [ "010" \< "01.0" ]; then echo "Wrong"; else echo "OK"; fi

阅读文档,[[ &lt; ]][ \&lt; ] 似乎应该工作相同,但他们没有。当字符串长度不同时,[[ &lt; ]] 似乎工作错误。我错过了什么吗?

预期结果是 4 x OK。测试日期:

  • CentOS 版本 6.4(最终版)- GNU Bash,版本 4.1.2(1)-release (x86_64-redhat-linux-gnu) (OK Wrong OK OK)
  • Ubuntu 14.04.2 (Trusty Tahr) LTS - GNU Bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu) (OK Wrong OK OK)
  • openSUSE 13.1 (Bottle) (x86_64) - GNU Bash,版本 4.2.53(1)-release (x86_64-suse-linux-gnu) (OK OK OK OK)

【问题讨论】:

  • 能否请您添加脚本的输出?
  • 第二个在GNU bash, version 4.3.39上对我说错了。
  • 我确认了奇怪的行为:输出说:“好的,错误的,好的,好的”;而对我来说,预期的输出是“好的,错误的,好的,错误的”;因为这些值在我的电脑上按“01”、“010”、“01.0”排序。
  • 请注意,奇怪的行为只发生在极限情况排序;使用单括号和双括号时似乎使用了不同的排序算法;这可能吗?
  • 查看 ASCII 表。出现在 0 之前,因此字符串的预期顺序应该是 01., 01.0, 010

标签: string bash comparison


【解决方案1】:

如果你想比较整数,你应该这样做:

if [[ 10 < 1 ]]; then echo "10 < 1"; else echo "10 > 1"; fi

# Result:
#
#   10 > 1

如果你想比较浮点数,你应该看看这个线程: How can I do float comparison in Bash?

你的例子:

echo "10 < 1.0" | bc
# Return: 0

echo "10 > 1.0" | bc
# Return: 1

【讨论】:

  • 好吧,看到这个答案不正确,我有点困惑。下面是一个命令示例: mat@lapdev001:~$ if [[ 11 ";fi > mat@lapdev001:~$ if [[ 11 ";fi "string" ]];然后回显“";fi > mat@lapdev001:~$ if [[ "string" > "string" ]];然后回显“";fi > mat@lapdev001:~$ if [[ "string" > "longstring" ]];然后回显“";fi
  • edit (change) your answer 添加其他信息,而不是在 cmets 中(但没有“编辑:”、“更新:”或类似- 答案应该看起来好像是今天写的)。评论可以随时删除。
【解决方案2】:

原因可能是从 Bash 4.1 开始, 字符串比较运算符尊重语言环境。

所以在两个系统之间可以有以下区别:

  1. 不同的区域设置 - 通过运行 locale 进行检查(有关不同区域设置的含义,请参阅 What does "LC_ALL=C" do?
  2. 即使语言环境相同,也可能会打开 shopt compat31 或 compat32(Bash 3.1 或 3.2 兼容模式),这意味着字符串比较不会考虑语言环境 - 通过运行 shopt 进行检查

进一步阅读:

【讨论】:

    【解决方案3】:

    这是来自help test的文档:

    字符串 1 > 字符串 2

    如果 STRING1 按字典顺序排在 STRING2 之后,则为真。

    以你的第一个if 语句为例:

    if [[ "010" < "01." ]]; then echo "Wrong"; else echo "OK"; fi
    

    在 Bash 中,字符串 "01." 按字典顺序字符串 "010" 之前排序(您可以在 Microsoft Excel 等其他工具中进行测试),因此比较返回 false。您的所有 4 个比较都是这种情况。

    请注意,在"01." 的末尾添加一个额外的0 并不会改变与"010" 相比的顺序,因此您仍然会得到相同的结果。

    【讨论】:

    • 我在 bash 4.2.53 (opensuse13.1);我得到“好的,错的,好的,好的”;所以他确实有道理......
    • 我也在使用 Bash 4.2.53,我对所有 4 个都很好。这真的很奇怪。
    • 当我对三个值进行排序时;我得到:“01”。 , "010", "01.0"
    • 确实很奇怪。在运行 bash 3.2.* 的 OSX 上,我得到 OKOKOKOK。在运行 bash 4.1.2 的 AWS Linux 上,我得到 OKWrongOKOK
    • 您可能会说我对发布此答案感到有点bashful。那怎么解释OP呢?
    猜你喜欢
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 2010-11-08
    • 2021-10-29
    • 2012-01-22
    • 2015-12-07
    相关资源
    最近更新 更多