算術拡張(先行ゼロ)でテスト

算術拡張(先行ゼロ)でテスト

次のksh88コードは、月[m]と年[y]の値を取り、先月の年[p_m]と先月[p_m_y]を計算します。

m は元の date コマンドから出てくるので、現在の月が 10 より小さい場合は前に 0 が付きます。

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ステートメントは失敗したように見え、mが1より大きい場合でも常に "else"コードを実行します。前にゼロを付けるのが問題かもしれないと思いますか? [[..]]を使っても同じことが起こります。

次のように変更すると機能します。

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

おそらくこれは文字列比較です。算術比較は機能しません。大きな問題ではなく、まだ解決できます。

ただし、正しい算術を使用してこれを操作する方法が必要です。 Base10拡張を強制しようとすると、何の効果もありません。

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

答え1

月が1 =>先月=> 12で年が減少したときに呼び出されるdc電卓を使用します。macro aそれ以外の場合は年を減らします。

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前にゼロがあるということではありません。 8進数で処理されても02まだ0です2。使用中のテストは次のとおりです。

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

しかし、m-1 > 1はと同じですm > 2。より2大きくないので、句が実行されます。テストを簡単なものに変更できます。2else

[ $m -gt 1 ]

しかし、シェルの算術関数を直接使用する方がはるかに簡単です。

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

この最後のポイントは、おそらくいくつかの説明が必要です。

ではp_mモジュラー操作を使用します。 (m + 10)%12「2ヶ月前(または10ヶ月後)」と同じです。ただし、12月は0として表示されます。次に、「先月、範囲1-12」を実装するために1つを追加します。

最後の行はより簡単です。値が1の場合、それ以外の場合(m==1)。 1以外の場合は現在の年に設定され、それ以外の場合は前の年に設定されます。1m0p_m_ym


ところで、あなたはこう言いました。

m は元の date コマンドから出てくるので、現在の月が 10 より小さい場合は前に 0 が付きます。

必ずしもそうではありません。私のシステムでは:

$ 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

したがって、数字が8進数として解釈されるのが心配な場合は、最後の数字を試してみることをお勧めします。

答え3

これはうまくいきます。次の環境でテストしましたksh

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

にも適用されます-gt

関連情報