bash函数返回if语句不起作用

时间:2019-01-26 19:28:29

标签: bash

我正在尝试重构此代码:

if [ $(($1 % 4)) -eq 0 ] && [ $(($1 % 100)) -ne 0 ] || [ $(($1 % 400)) -eq 0 ] ; then
    echo $T
else
    echo $F
fi

变成这样:

if divisibleBy4 && notDivisibleBy100 || divisibleBy400; then
    echo $T
else
    echo $F
fi

请注意

T="true"
F="false"

divisibleBy4函数如下:

divisibleBy4() {
    return  [ $(($1 % 4)) -eq 0 ]
}

但是我已经尝试了几次迭代,包括我认为肯定会奏效的迭代。

divisibleBy4() {
    if [ $(($1 % 4)) -eq 0  ]; then
    return 1
    else return 0
    fi
}

有什么主意如何正确修复语法,以便可以将其重构为函数并在if语句中使用它们?

测试时我看到了错误

  

语法错误:预期的操作数(错误令牌为“%4”)

我尝试过的另一件事是,但似乎仍然行不通:

INPUT=$1

divisibleBy4() {
    if [ $(($INPUT % 4)) -eq 0  ]; then
         return 1
    else return 0
    fi
}

notDivisibleBy100() {
    if [ $(($INPUT % 100)) -ne 0]; then
         return 1
    else return 0
    fi
}

divisibleBy400() {
    if [ $(($INPUT % 400)) -eq 0  ]; then
         return 1
    else return 0
    fi
}


if divisibleBy4 && notDivisibleBy100 || divisibleBy400; then
    echo $T
else
    echo $F
fi

INPUT=$1

divisibleBy4() {
    return $((!($INPUT %4)))
}
notDivisibleBy100() {
    return $(($INPUT %100))
}
divisibleBy400() {
    return $((!($INPUT %400)))
}

(( divisibleBy4 && notDivisibleBy100 || divisibleBy400 )) && echo "true" || echo "false"

3 个答案:

答案 0 :(得分:3)

您想检测a年! 直接使用数学模式的完整解决方案:

a="$1"; (( !(a%4) && a%100 || !(a%400) )) && echo true || echo false

或仿佛-然后-其他

a="$1";
if (( !(a%4) && a%100 || !(a%400) )); then
    echo true
else
    echo false

答案 1 :(得分:1)

最简单,最直接的答案是只创建仅包含测试本身的函数:

INPUT=$1

divisibleBy4() {
    [ $(($INPUT % 4)) -eq 0  ]
}

notDivisibleBy100() {
    [ $(($INPUT % 100)) -ne 0 ]
}

divisibleBy400() {
    [ $(($INPUT % 400)) -eq 0  ]
}

之所以可行,是因为没有return的函数将隐式返回该函数中最后一个命令的状态;在这些情况下,这就是测试命令(注意:[是一个命令,即使它看起来不像一个命令),因此这些函数只是直接返回测试结果。

不过,我将至少对它们进行一次更改:它们都测试了shell变量INPUT的值;更好的做法是实际传递函数所操作的数据作为参数。因此,最好执行以下操作:

divisibleBy4() {
    [ $(($1 % 4)) -eq 0  ]
}

if divisibleBy4 "$1" ...

而不是:

divisibleBy4() {
    [ $(($INPUT % 4)) -eq 0  ]
}

INPUT=$1
if divisibleBy4 ...

请注意,您还可以通过以下方式捆绑整个leap年检查:

isLeapYear() {
    [ $(($1 % 4)) -eq 0 ] && [ $(($1 % 100)) -ne 0 ] || [ $(($1 % 400)) -eq 0 ]
}

if isLeapYear "$1"; then

或使用建议的简单形式@Wiimm:

isLeapYear() {
    (( !($1%4) && $1%100 || !($1%400) ))
}

对于您所使用的shell变量,为了避免与许多具有特殊含义或功能的全大写字母变量名称发生意外冲突,首选使用小写或大小写混合的字母。

答案 2 :(得分:0)

每个命令都设置一个结果代码。如果要强制每个计算在单独的函数中进行,可以说

divisibleBy4() {
    $((!("$1" % 4)))
}
notDivisibleBy100() {
     $(("$1" %100))
}
divisibleBy400() {
     $((!("$1" %400)))
}

(divisibleBy4 "$1" &&
 notDivisibleBy100 "$1" ||
 divisibleBy400 "$1") &&
echo "true" || echo "false"

但是,在亚原子级别上破坏逻辑功能并不能真正帮助提高可读性和可维护性。也许,如果您想使每个部分合理地自我补充,请使用注释。

is_leap () {
    # Divisible by 4?
    (("$1" % 4 == 0)) || return
    # Not divisible by 100?
    (("$1" % 100 > 0)) && return
    # Divisible by 400?
    (("$1" % 400 == 0))
}

...尽管这里的评论似乎多余。