使用算术扩展进行测试(前导零)

使用算术扩展进行测试(前导零)

以下 ksh88 代码采用月份 [m] 和年份 [y] 的值,并计算出上个月 [p_m] 和上个月 [p_m_y] 的年份。

m 最初源自 date 命令,因此如果当前月份 < 10,则有一个前导零。

m=02
y=2017

if [ $((m-1)) -gt 1 ]
then
    p_m=$((m-1))
    p_m_y=$((y))
else
    p_m=12
    p_m_y=$((y-1))
fi

在此示例中,p_m 设置为 12,p_m_y 为 2016,因此 if 语句似乎失败并且总是触发“else”代码......即使 m 大于 1。我认为前导零可能是问题所在?如果我使用 [[ .. ]] 也会发生同样的事情。

如果我将其修改为以下内容,它就可以工作

if [[ $((m-1)) != 01 ]]

想必这现在是字符串比较,算术比较不起作用。这不是一个大问题,我仍然可以解决这个问题。

但应该有一种方法可以使用正确的算术让它工作。如果我尝试强制进行 base10 扩展,则不会产生任何效果。

if [[ $((10#$m-1)) -gt 1 ]]

答案1

我们使用dc计算器,macro a当月份为 1 月 => 上个月 => 12 且年份递减时,将调用 。否则,我们只是减少年份。

m=01
y=2011

set X `echo "[sa 1- 12]sa $y $m d1- r1- r0 =af" | dc`; shift

p_m=$1  p_m_y=$2

echo "Current month:$m   Current year: $y"
echo "   Prev month:$p_m Prev month year: $p_m_y"

答案2

您显示的具体示例中的问题不在于m有一个前导零 - 即使它被视为八进制,02仍然只是2。您使用的测试是:

[ $((m-1)) -gt 1 ]

m-1 > 1相当于m > 2.由于2不大于2,因此else将运行该子句。您可以将测试更改为简单的

[ $m -gt 1 ]

但直接使用 shell 的算术功能会简单得多:

m=02
y=2017
p_m=$(( (m+10)%12 + 1 ))
p_m_y=$(( y - (m==1) ))

最后一点可能值得一些解释:

对于p_m,我们使用模运算。 (m + 10)%12相当于“两个月前(或十个月后),只不过 12 月被列为 0”。然后我们添加一个以实现“上个月,范围 1-12”。

最后一行更简单。 (m==1)1ifm数值等于 1,否则0。如果不是 1,则设置为当前年份,否则设置为上一年p_m_ym


顺便说一句,你说:

m 最初源自 date 命令,因此如果当前月份 < 10,则有一个前导零。

情况不一定如此。在我的系统上:

$ date
2017年  5月  9日 火曜日 13:58:53 EDT
$ LC_ALL=en_US.UTF-8 date
Tue May  9 13:58:53 EDT 2017
$ date '+%Y %m %d' | sed 's/ 0*/ /g'
2017 5 9

因此,如果您担心数字被解释为八进制,您可能想尝试最后一个。

答案3

这应该可行,我刚刚在以下环境中测试了它ksh

if [[ $((m-1)) -eq 1 ]]; then echo "Equal"; fi

也适用于-gt

相关内容