Bash 测试运算符 [[ ... -eq ... ]] 中的错误或功能?

2023-12-08

有人可以解释一下以下之间的区别:

VAR=1xyz && [[ $VAR -eq $VAR ]] 2>/dev/null && echo "Yes, VAR = $VAR is an integer" || echo "No, VAR = $VAR is NOT an integer"
No, VAR = 1xyz is NOT an integer

And:

VAR=xyz1 && [[ $VAR -eq $VAR ]] 2>/dev/null && echo "Yes, VAR = $VAR is an integer" || echo "No, VAR = $VAR is NOT an integer"
Yes, VAR = xyz1 is an integer

这是 Bash 中的错误还是功能?

如果代替[[ ... ]] I use [ ... ],我得到了预期的结果$VAR is not在这两种情况下都是整数。


要理解这里发生了什么,您需要明确两件事:

1. 条件结构的确切含义

在大多数语言中,都有某种可以解释为 true 或 false 的值。这可能是布尔数据类型、整数(其中 0 为假,其他一切为真)或按类型实现的某种“真实性”概念。

但 Posix shell 没有“true”和“falsey”值。他们所拥有的是可能成功或失败的陈述。 “成功”和“失败”的含义主要由命令本身来确定,但 bash 本身会将某些行为归类为失败。例如,如果 shell 无法确定命令名称所指的内容,它将认为该命令失败:

$ undefined_command && echo Yes || echo No
undefined_command: command not found
No

此外,如果命令被信号终止,例如分段错误,shell 会将其视为失败:

$ ./segfault && echo Yes || echo No
Segmentation fault (core dumped)
No

但许多命令也会发出失败信号,即使错误不是致命的。 (他们通过将其状态设置为非零值来做到这一点。)例如,ls如果任何文件名参数不存在(即使其他文件名参数存在),则返回失败:

$ ls no_file exists && echo Yes || echo No
ls: cannot access 'no_file': No such file or directory
-rw-rw-r-- 1 rici rici 0 May  7 13:13 exists
No

如图所示,通常(尽管并非总是)会向 stderr 打印一条错误消息,其中给出了有关失败原因的一些提示。如果你想让自己感到困惑,通常可以抑制错误消息:

$ undefined_command 2>/dev/null && echo Yes || echo No
No
$ ls no_file exists 2>/dev/null && echo Yes || echo No
-rw-rw-r-- 1 rici rici 0 May  7 13:13 exists
No

这正是您在最初的问题中所做的。如果我们不隐藏错误消息,发生的事情就会变得更加明显:

$ VAR=1xyz && [[ $VAR -eq $VAR ]] && echo Yes || echo No
bash: [[: 1xyz: value too great for base (error token is "1xyz")
No
$ VAR=xyz1 && [[ $VAR -eq $VAR ]] && echo Yes || echo No
Yes

换句话说,尝试使用字符串1xyz作为一个数字(因为-eq is numericequal) 会产生错误,该错误被视为失败。然而,字符串xyz1是一个有效的数值。我们将在下一节中了解为什么会出现这种情况。

但在我们开始之前,我们需要注意的是[[ ... ]] is a command(尽管是 bash 扩展),shell 没有布尔值这一规则也不例外。与任何其他命令一样,[[可以成功也可以失败;它的文档表明,如果它将其参数评估为“true”,则它会成功。虽然在bash中[[是一个内置命令——必然如此,因为它需要不同的参数解析规则——它仍然是一个命令,并且它本身评估其参数,就像[.

2. 算术评估的特殊性

算术评估发生在扩展中$(( ... ))(在任何 Posix shell 中),以及许多其他数字上下文(在 Bash 和扩展 Posix 标准的其他 shell 中),包括算术条件(( ... ))以及内部数字比较运算符的参数[[ ... ]] and $[[ ... ]]。在 bash 中,算术求值还用于对声明为算术的变量进行赋值(使用declare -i) 以及数组的下标(不是关联数组)。

就这个问题而言,算术求值最重要的特征是参数可以是 shell 变量的名称(只是名称,没有$)。在这种情况下,如果可能,该变量的值将转换为整数,并用作参数。虽然 Posix 标准没有要求,但几乎所有 shell 都会将未定义的变量或值为空的变量视为数值 0。但是,如果该变量具有无法转换为数字的非空值,则产生错误。

这与变量名前面带有 a 的情况略有不同$。如果变量名前面有$,那么普通参数替换将正常发生在计算算术表达式之前。因此,在问题的第二个例子中,

VAR=xyz1 && [[ $VAR -eq $VAR ]] && echo Yes || echo No

参数展开的结果将是

[[ xyz1 -eq xyz1 ]]

自从xyz1(大概)未定义,它将被评估为将 0 与 0 进行比较,这是正确的(因此该命令将成功)。如果出现同样的结果xyz1被定义为数字字符串,但如果其值无法转换为整数则不会:

$ VAR=xyz1 && xyz1=42 && [[ $VAR -eq $VAR ]] && echo Yes || echo No
Yes
$ VAR=xyz1 && xyz1=42z && [[ $VAR -eq $VAR ]] && echo Yes || echo No
bash: [[: 42z: value too great for base (error token is "42z")
No

Bash 的数值计算规则实际上要复杂得多(如果应用于不受信任的输入,则不安全)。我不会详细介绍所有细节,但基本上 bash 会对value其名称在算术求值中用作参数的变量。实际上,这允许变量名称的递归替换,但它也允许您将变量的值设置为更复杂的值:

$ x=y+7
$ y=35
$ echo $((x))
42
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Bash 测试运算符 [[ ... -eq ... ]] 中的错误或功能? 的相关文章

随机推荐

  • 如何在PyQt5中使用QtWebEngine createWindow

    我正在尝试制作一个包含 QWebEngineView 的窗口 现在我希望浏览器能够处理创建窗口或 blank 类型触发器 或者专门在需要时在新窗口中打开 URL 在下面的代码中 当浏览器需要创建窗口时 会调用 createwindow 但不
  • Lua中计算字符串转换为int

    我正在尝试将包含多个数字的字符串转换为单个 int 像这样 x 5 5 amount of numbers is not constant y tonumber x print y 这样做的结果是nil虽然应该是10 整数 我解决这个问题的
  • MariaDB 10.2 和 Openssl 1.1.0e 出现“不完整类型 MD5_CONTEXT”错误

    我无法在 CentOS 7 中构建启用 RocksDB 的 MariaDB 10 2 它有以下编译错误 root mariadb 10 2 mysys ssl my md5 cc In function void md5 result MD
  • 嵌套 JSON 数组和 D3JS

    我正在尝试使用嵌套 json 数组通过 d3 js 绘制多系列图表 我在这个网站和其他网站上查看了很多地方 虽然有类似的主题 但我似乎无法使语法适用于我的特定问题 这是一个简单的问题 制作折线图 如下所示 http bl ocks org
  • 在 ScriptSharp 项目中对 C# 代码进行单元测试

    我使用 ScriptSharp 创建 RIA 应用程序 除了一些奇怪的地方之外 效果还不错 然而 使用 Firebug 查找和修复问题并不是很方便 由于 scriptsharp 还提供了一个 Dll 我希望使用一个单独的测试项目 使用 Nu
  • ReadString() 是否丢弃换行符后的字节?

    我正在尝试通过以下方式从网络连接读取数据 func getIn conn net Conn for in err bufio NewReader conn ReadString n if err nil fmt Printf err Err
  • 更正 Android 中的印地语 (Unicode) 渲染

    我成功添加了自定义字体 DroidSansFallBack ttf 以显示印地语字符而不是 Pre ICS 上的块 无论如何 4 1 上一切都运行良好 但 Froyo 和 Gingerbread 上的渲染顺序是错误的 我明白问题没有解决ht
  • Homebrew 拒绝链接 OpenSSL

    我正在使用 OSX 10 11 6 Homebrew 版本 0 9 9m OpenSSL 0 9 8zg 2015 年 7 月 14 日 我正在尝试使用 dotnetcore 并遵循他们的指示 我已经升级 安装了最新版本的 openssl
  • Excel 2007 中的 Application.filesearch 带循环

    我已经进行了多次搜索 并且在使用现在不存在的 filesearch 时很难找到正确的代码 我已经研究过使用 Dir 和 FileSystemObject 但在搜索后使用循环时没有任何混乱 我希望你能够帮助我得出一个更容易的结论 简而言之 我
  • excel 2007宏验证输入单元格的数据并显示消息框(如果不正确)

    请有人帮忙编写以下代码 它在以下行给我一个错误 Set range C5 L14 这是完整的代码 Private Sub Worksheet Change ByVal Target As Excel range Dim ws As Work
  • if-else 与 ifelse 与列表的比较

    为什么 if else 结构和函数 ifelse 的行为不同 mylist lt list list a 1 b 2 list x 10 y 20 l1 lt ifelse sum sapply mylist class list 0 my
  • 如何异步调用 AWS Lambda 函数

    有谁知道异步而不是同步调用 Amazon AWS Lambda 函数的当前正确方法 AWS Java SDK 中的 InvokeAsync API 仍然可用 但标记为已弃用 他们建议您使用 Invoke API 我不明白为什么他们会强迫我们
  • 捆绑脚本无法正常工作 MVC

    我捆绑了 jquery 验证脚本 例如 bundles Add new ScriptBundle bundles jqueryval Include Scripts jquery unobtrusive Scripts jquery val
  • 强制 VB.NET 生成与 C# 相同的字符串比较表达式?

    这里有些类似的问题 C 和 VB Net 字符串比较的区别 但和我现在问的不一样 我正在创建一个简单的表达式遍历器 它将 lambda 转换为 SQL WHERE 子句 我这样称呼它 GetEntities
  • 如何在 Android Studio 0.5.1 上导入模块?

    我刚刚将 Android Studio 更新到 0 5 1 我需要将 Facebook SDK 导入到我的项目中 下列的脸书的指南 我应该 使用 Command 向下箭头打开 项目结构 对话框 在 OS X 上 选择左侧导航栏下的模块 单击
  • Android:http登录没有达到预期的效果

    我似乎无法让登录页面正常工作 它一直告诉我我的用户名 密码不正确 而我显然知道它们不正确 所以我开始调试并弹出 log v 我发现了一些有趣的东西 查找显示 class LogMeIn extends AsyncTask
  • MySQL统计最近7天的数据

    我有以下架构 表票 Field Type Null Key Default Extra id int 10 NO PRI NULL auto increme
  • 如何使用 cbt 从 BigTable 中删除带有前缀键的行范围

    看起来我可以用 cbt 读取带有前缀键的行 cbt project someproject instance someinstance read sometable prefix abc 但是如何使用 cbt 命令删除上述命令选择的那些行呢
  • JSONObject 包含转义字符

    我正在构建一个模拟器来将 JSON 数据发布到我正在运行的服务 JSON 应如下所示 sensor id SENSOR1 name SENSOR type Temperature value 100 12 lastDateValue Dat
  • Bash 测试运算符 [[ ... -eq ... ]] 中的错误或功能?

    有人可以解释一下以下之间的区别 VAR 1xyz VAR eq VAR 2 gt dev null echo Yes VAR VAR is an integer echo No VAR VAR is NOT an integer No VA