【问题标题】:Undesired result if condition如果条件不希望的结果
【发布时间】:2016-09-19 15:16:25
【问题描述】:

以下是我在其上应用以下 unix 脚本的文件。

    0.30 2.30 - - - - - - -
    2.30 3.30 - - NA NA - - -
    3.30 4.30 - - NA NA - - -
    4.30 5.30 - - - - - - -
    5.30 6.30 - - NA NA - - -
    6.30 0.30 - - - - - - -

##Time=`echo $(date) | awk -F ' ' '{print $4}' | awk -F ':' '{print $1}'` 
Time=05;
Result="False";
while [[ "${Result}" != "True" ]]
do
    while read -r f1 f2 f3 f4 f5 f6 f7 f8 f9
    do
        if [[ "${Time}" -ge "${f1}" && "${Time}" -le "${f2}" ]]
        then 
                echo $Time is between $f1 $f2 True
                Result="True";
        else
                echo $Time is between $f1 $f2 False
        fi
    done < consolidated.txt
done

我得到以下结果:请注意 if 条件被满足了两次。 05 不在 5.30 和 6.30 之间,它仍然返回 true。 我在这里错过了什么。

05 is between 0.30 2.30 False
05 is between 2.30 3.30 False
05 is between 3.30 4.30 False
05 is between 4.30 5.30 True
05 is between 5.30 6.30 True
05 is between 6.30 0.30 False

【问题讨论】:

  • 这是什么语言?
  • 这是 ksh 中的脚本
  • 我们有一个标签。首次发布问题时,您需要包含所有这些重要的详细信息。
  • 请注意,您使用对称条件 time &gt;= start &amp;&amp; time &lt;= end 的测试会导致问题,即 5.30 将同时属于 4.30 - 5.30 和 5.30 - 6.30 时间范围。通常最好使用非对称条件,如time &gt;= start &amp;&amp; time &lt; end,而不是在数据中连续设置范围时。这是一个开闭区间。

标签: unix ksh aix


【解决方案1】:

您遇到的问题是由于行Time=05; ksh 没有将其解释为浮点值。 let 会强制它这样做。

$ Time=05;echo $Time
05
$ let Time=05;echo $Time
5

另一个常见的成语是Time=$(echo $Time |bc)

这是您的逻辑的另一种措辞:

$echo $Time $f1 $f2
05 5.30 6.30
$
$let Time=05     
$ if [[ (( $Time > $f1 )) && (( $Time < $f2 )) ]]
> then 
>        echo $Time is between $f1 $f2 True
> else
>        echo $Time is between $f1 $f2 False
>fi    
5 is between 5.30 6.30 False

(( ... )) 是一个类似于 [[ ... ]] 的数字条件
它设计用于ifwhile 构造。

您可以在学习 Korn Shell 的第 6.2.2 节中找到更多详细信息 here

【讨论】:

    【解决方案2】:

    各种问题可见:

    • 代码中的外循环有问题。如果consolidated.txt 中的任何时间范围都不匹配,则${Result} 仍然是False,并且外循环永远不会终止。
    • 数据中的最后一个时间范围 6.30 0.30 永远不会匹配任何内容,因为该范围的结尾在数值上小于该范围的开头。
    • 在您使用time &gt;= start &amp;&amp; time &lt;= end 的条件下,如果时间值为5.30,那么这将匹配4.30 5.30 范围(等于结束时间)和5.30 6.30 范围(等于到开始时间)。

    与 Bash 不同,Korn shell 确实支持浮点运算,这很有用。

    您应该使用(( … )) 和(浮点)数字比较(&gt;=&lt;),而不是 [[ … ]] 和使用字符串比较(-ge-le)。

    将这些更改组合到一个脚本中,并忽略 Result 变量,因为它在这里不相关,您会得到:

    #!/bin/ksh
    
    for Time in 0 3 05 5.30 7.00
    do
        while read -r f1 f2 f3 f4 f5 f6 f7 f8 f9
        do
            if (( "${Time}" >= "${f1}" && "${Time}" < "${f2}" ))
            then echo "${Time} is between ${f1} and ${f2} True"
            else echo "${Time} is between ${f1} and ${f2} False"
            fi
        done << EOF
        0.30 2.30 - - - - - - -
        2.30 3.30 - - NA NA - - -
        3.30 4.30 - - NA NA - - -
        4.30 5.30 - - - - - - -
        5.30 6.30 - - NA NA - - -
        6.30 24.00 - - - - - - -
    EOF
    done
    

    是的,此处文档末尾的EOF 确实需要位于左边距。您可以使用&lt;&lt;-'EOF' 并缩进结束标记EOF,只要缩进是制表符,而不是空格。

    这个脚本的输出是:

    0 is between 0.30 and 2.30 False
    0 is between 2.30 and 3.30 False
    0 is between 3.30 and 4.30 False
    0 is between 4.30 and 5.30 False
    0 is between 5.30 and 6.30 False
    0 is between 6.30 and 24.00 False
    3 is between 0.30 and 2.30 False
    3 is between 2.30 and 3.30 True
    3 is between 3.30 and 4.30 False
    3 is between 4.30 and 5.30 False
    3 is between 5.30 and 6.30 False
    3 is between 6.30 and 24.00 False
    05 is between 0.30 and 2.30 False
    05 is between 2.30 and 3.30 False
    05 is between 3.30 and 4.30 False
    05 is between 4.30 and 5.30 True
    05 is between 5.30 and 6.30 False
    05 is between 6.30 and 24.00 False
    5.30 is between 0.30 and 2.30 False
    5.30 is between 2.30 and 3.30 False
    5.30 is between 3.30 and 4.30 False
    5.30 is between 4.30 and 5.30 False
    5.30 is between 5.30 and 6.30 True
    5.30 is between 6.30 and 24.00 False
    7.00 is between 0.30 and 2.30 False
    7.00 is between 2.30 and 3.30 False
    7.00 is between 3.30 and 4.30 False
    7.00 is between 4.30 and 5.30 False
    7.00 is between 5.30 and 6.30 False
    7.00 is between 6.30 and 24.00 True
    

    如果将&lt; 条件更改为&lt;=,这相当于问题使用的内容,那么您将得到输出:

    …
    5.30 is between 3.30 and 4.30 False
    5.30 is between 4.30 and 5.30 True
    5.30 is between 5.30 and 6.30 True
    5.30 is between 6.30 and 24.00 False
    …
    

    最后一个范围为6.30 0.30,输出的最后部分如下所示:

    …
    7.00 is between 5.30 and 6.30 False
    7.00 is between 6.30 and 0.30 False
    

    【讨论】:

    • 非常感谢您区分 [[...]] 和 ((...)) 用于字符串和数字比较。我已经编辑了脚本,它似乎工作正常。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多