谨防三月十五日凯撒

谨防三月十五日凯撒

谨防三月十五日凯撒

我在使用 bash 时遇到一个奇怪的错误:${string:offset:length}

三月中旬的第五行输出有错误:

$ substring_test.sh
     March 2018       
Su Mo Tu We Th Fr Sa  
             1  2  3  T=   T=   T=   T=   T= 1 T= 2 T= 3 
 4  5  6  7  8  9 10  T= 4 T= 5 T= 6 T= 7 T= 8 T= 9 T=10 
11 12 13 14 15 16 17  T= T= T= 1 T= 1 T= 1 T= 1 T= 1 
18 19 20 21 22 23 24  T=18 T=19 T=20 T=21 T=22 T=23 T=24 
25 26 27 28 29 30 31  T=25 T=26 T=27 T=28 T=29 T=30 T=31 
                      T=   T=   T=   T=   T=   T=   T=   

它显示:

T= T= T= 1 T= 1 T= 1 T= 1 T= 1

但它应该展示:

T=11 T=12 T=13 T=14 T=15 T=16 T=17

代码非常简单:

#!/bin/bash

cal > /tmp/terminal

CalLineCnt=1
Today=$(date +"%d")

# Prefix with space when length < 2
if [[ ${#Today} < 2 ]] ; then
    Today=" "$Today
fi

while IFS= read -r Cal; do
    printf "$Cal"
    if [[ $CalLineCnt > 2 ]] ; then
        # See if today is on current line & invert background
        for (( j=0 ; j <= 18 ; j += 3 )) ; do
            Test=${Cal:$j:2}    # Current day on calendar line
printf "T=$Test "
            if [[ "$Test" == "$Today" ]] ; then
                printf "Offset: $j "
            fi
        done
    fi
    tput cud1           # Down one line
    CalLineCnt=$((++CalLineCnt))
done < /tmp/terminal

有人能给我指出正确的方向吗?


最终结果

应用cal -h下面推荐的修复方法效果很好,直到Ubuntu 18.04 LTS已于2018年4月28日发布并测试,现采用@Steve H建议的修复方法:

现在.png

有些人很好奇代码的作用,所以我提供了上面的屏幕截图。其他人要求提供完整代码,可在此处获取:我如何才能获得这个终端启动画面?

答案1

你的问题是cal已经突出显示了当前日期,并且控制代码正在抛出偏移量

在十六进制编辑器中查看/tmp/terminal。今天(11 号)是:5F 08 31 5F 08 31,而不是31 31

用于cal -h关闭今天日期的自动突出显示。

答案2

@Martin Thornton 如果 cal 的所有实现都能识别 -h 来关闭格式化,那就没问题了。Debian 却不能,尽管 man 建议它这样做。它反而会显示用法。所以这可以工作。

cal > /tmp/terminal1
tr -cd '\11\12\15\40\60-\136\140-\176' < /tmp/terminal1  > /tmp/terminal

该文件获取带有格式化的 cal 输出,下一行删除我们不想要的任何内容并让其余代码完成其工作。

相关内容