Bash测试值的评估

3

我正在学习关于shell脚本的知识,特别是涉及到的shell命令有test[ ][[ ]](( ))。我编写了一个非常简单的脚本来测试我的理解。它接受三个参数,如果这三个参数都是整数(并且第二个参数小于第三个参数),则它会测试第一个参数是否在第二个参数和第三个参数之间的范围内。下面是示例代码:

#!/bin/bash
#test if arg1 is contained in the range [arg2, arg3]

function isint()
{
    if [[ "$1" =~ ^-?[0-9]+$ ]]; then
    echo $1 is integer
    return 0
    else
    echo $1 is not integer
    return 1
    fi
}


if [[ $(isint $1) && $(isint $2) && $(isint $3) &&  $2 -lt $3  ]]; then
    if [[ $2 -le $1  &&  $1 -le $3 ]]; then
    echo "$1 is in the range [$2,$3]"
    else
    echo "$1 is not in the range [$2,$3]"
    fi
else
    echo usage: $0 INT1 INT2 INT3
fi

这是我的问题:前面的脚本不起作用,

if [[ $(isint $1) && $(isint $2) && $(isint $3) &&  $2 -lt $3  ]] 

如果我想得到想要的结果,就需要将测试条件更改为:不会永远评估为true。

if [[ !$(isint $1) && !$(isint $2) && !$(isint $3) &&  $2 -lt $3  ]]

我不明白为什么这个脚本能够工作,我理解test[[ ]] 命令都会评估传递给它们的表达式,0 评估为 true ,而1 评估为 false。在我的情况下,如果正确的参数被传递到脚本中,isint调用将评估为0,也就是真,那么为什么需要反转它们才能让脚本按照我的意愿工作呢?
谢谢您的帮助。

1
提示:在脚本顶部添加 set -x 或在第一行的 shebang 中添加 -x#!/bin/bash -x。这将让您看到每一行代码的执行情况。 - Harvey
2个回答

4

您的问题在于您在调用isint时使用了$()。这会将命令替换为调用isint的标准输出,因此在这种情况下,您实际运行的是:

if [[ "$1 is integer" && "$2 is integer" && "$3 is integer" &&  $2 -lt $3  ]] 

你希望使用返回值,所以只需删除 $() 并将 isint 移出括号:
if isint "$1" && isint "$2" && isint "$3" &&  [[ "$2" -lt "$3"  ]]

我添加了一些引号:在整个过程中,你真的应该引用你的论点。

1
括号是一个不好的选择 - 它们会导致子shell被生成,这会带来性能损失。如果您想要分组而不需要显式地生成子shell,请使用花括号。然而,我并不认为有任何需要显式分组:if允许以复合命令开始。 - Charles Duffy
1
虽然如此,我认为这并不值得受到负评——这个答案的核心是正确的。可能会将它改为 [[ "$1 是整数" && "$2 是整数" ...,用引号括起来以使事情更清晰一些?但不是我的负评。 - Charles Duffy
@CharlesDuffy 说得对,没错。那个踩票可能是因为我在这个答案的v1版本中有一个相当严重的拼写错误。 - Chris - Regenerate Response
1
(顺便说一下,我会使用算术环境,使其为 (( $2 < $3 )))。 - Charles Duffy
谢谢,你的解决方案与@harvey的类似,因为有额外的解释,我选择了你的答案。 - ColdCoffeeMug

4
你把字面值和返回码混淆了。应该是这样的:
isint "$1" && isint "$2" && isint "$3" && [[ "$2" -lt "$3"  ]]

这意味着运行这四个命令并查看它们是否全部为true(返回代码== 0)。


谢谢,你的解决方案有效,但现在我更加困惑了。首先,你使用 && 作为 AND_IF 命令,对吗?其次,我认为在 if 后面需要一个 test 命令(或类似的命令),但是任何命令都可以完成任务,因为任何命令都有返回值。 - ColdCoffeeMug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接