UNIX 中的日历突出显示

UNIX 中的日历突出显示

我尝试过几次,但无法突出显示年历中的多个日期

cal -y
2022                               

       January               February                 March       
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                   1          1  2  3  4  5          1  2  3  4  5   
 2  3  4  5  6  7  8    6  7  8  9 10 11 12    6  7  8  9 10 11 12   
 9 10 11 12 13 14 15   13 14 15 16 17 18 19   13 14 15 16 17 18 19   
16 17 18 19 20 21 22   20 21 22 23 24 25 26   20 21 22 23 24 25 26   
23 24 25 26 27 28 29   27 28                  27 28 29 30 31         
30 31                                                                
        April                   May                   June        
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                1  2    1  2  3  4  5  6  7             1  2  3  4   
 3  4  5  6  7  8  9    8  9 10 11 12 13 14    5  6  7  8  9 10 11   
10 11 12 13 14 15 16   15 16 17 18 19 20 21   12 13 14 15 16 17 18   
17 18 19 20 21 22 23   22 23 24 25 26 27 28   19 20 21 22 23 24 25   
24 25 26 27 28 29 30   29 30 31               26 27 28 29 30         
                                                                     
        July                  August                September     
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                1  2       1  2  3  4  5  6                1  2  3   
 3  4  5  6  7  8  9    7  8  9 10 11 12 13    4  5  6  7  8  9 10   
10 11 12 13 14 15 16   14 15 16 17 18 19 20   11 12 13 14 15 16 17   
17 18 19 20 21 22 23   21 22 23 24 25 26 27   18 19 20 21 22 23 24   
24 25 26 27 28 29 30   28 29 30 31            25 26 27 28 29 30      
31                                                                   
       October               November               December      
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                   1          1  2  3  4  5                1  2  3   
 2  3  4  5  6  7  8    6  7  8  9 10 11 12    4  5  6  7  8  9 10   
 9 10 11 12 13 14 15   13 14 15 16 17 18 19   11 12 13 14 15 16 17   
16 17 18 19 20 21 22   20 21 22 23 24 25 26   18 19 20 21 22 23 24   
23 24 25 26 27 28 29   27 28 29 30            25 26 27 28 29 30 31   
30 31                                                                

我想突出显示年历中的多个日期。在UNIX下可以吗?

答案1

您可以编写一个脚本来调整cal输出,例如使用任何 awk:

$ cat tgtDates
January 25
June 13

$ cat tst.sh
#!/usr/bin/env bash

cal 2022 |
awk '
    BEGIN {
        highlightOn  = "["
        highlightOff = "]"
    }
    NR==FNR {
        tgtDates[$0]
        next
    }
    NF == 3  { split($0,months); print; next } # month list
    !/[0-9]/ { print; next }            # blank line or days list
    {                                   # dates list
        for ( mthNr=1; mthNr<=3; mthNr++ ) {
            mthName   = months[mthNr]
            inDayNrs  = substr($0,1,20)
            outDayNrs = ""
            while ( match(inDayNrs,/[0-9]+/) ) {
                inDayNr   = substr(inDayNrs,RSTART,RLENGTH)
                curDate   = mthName " " inDayNr
                outDayNr  = (curDate in tgtDates ? highlightOn inDayNr highlightOff : inDayNr )
                outDayNrs = outDayNrs substr(inDayNrs,1,RSTART-1) outDayNr
                inDayNrs  = substr(inDayNrs,RSTART+RLENGTH)
            }
            printf "%s   ", outDayNrs inDayNrs
            $0 = substr($0,24)
        }
        print ""
    }
' "$1" -

$ ./tst.sh tgtDates
                               2022
       January               February                 March
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                   1          1  2  3  4  5          1  2  3  4  5
 2  3  4  5  6  7  8    6  7  8  9 10 11 12    6  7  8  9 10 11 12
 9 10 11 12 13 14 15   13 14 15 16 17 18 19   13 14 15 16 17 18 19
16 17 18 19 20 21 22   20 21 22 23 24 25 26   20 21 22 23 24 25 26
23 24 [25] 26 27 28 29   27 28                  27 28 29 30 31
30 31
        April                   May                   June
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                1  2    1  2  3  4  5  6  7             1  2  3  4
 3  4  5  6  7  8  9    8  9 10 11 12 13 14    5  6  7  8  9 10 11
10 11 12 13 14 15 16   15 16 17 18 19 20 21   12 [13] 14 15 16 17 18
17 18 19 20 21 22 23   22 23 24 25 26 27 28   19 20 21 22 23 24 25
24 25 26 27 28 29 30   29 30 31               26 27 28 29 30

        July                  August                September
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                1  2       1  2  3  4  5  6                1  2  3
 3  4  5  6  7  8  9    7  8  9 10 11 12 13    4  5  6  7  8  9 10
10 11 12 13 14 15 16   14 15 16 17 18 19 20   11 12 13 14 15 16 17
17 18 19 20 21 22 23   21 22 23 24 25 26 27   18 19 20 21 22 23 24
24 25 26 27 28 29 30   28 29 30 31            25 26 27 28 29 30
31
       October               November               December
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
                   1          1  2  3  4  5                1  2  3
 2  3  4  5  6  7  8    6  7  8  9 10 11 12    4  5  6  7  8  9 10
 9 10 11 12 13 14 15   13 14 15 16 17 18 19   11 12 13 14 15 16 17
16 17 18 19 20 21 22   20 21 22 23 24 25 26   18 19 20 21 22 23 24
23 24 25 26 27 28 29   27 28 29 30            25 26 27 28 29 30 31
30 31

显然,我只是将目标日期包装在[...]上面,以便它们可见以显示命令正在工作,这就是导致行布局移动、为日期着色而不是仅更改的原因:

        highlightOn  = "["
        highlightOff = "]"

更改背景和/或前景色以突出显示的内容,您甚至可以为您喜欢的任何不同类型的事件设置不同的背景/前景色,例如:

$ cat tgtDates
January 25 Birthday
June 13 Meeting
September 2
December 25 Holiday

$ cat tst.sh
#!/usr/bin/env bash

cal 2022 |
awk -v today="$(date +'%B %-d')" '
    BEGIN {
        split("BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE",tputColors)
        for (i in tputColors) {
            colorName = tputColors[i]
            colorNr = i-1

            cmd = "tput setaf " colorNr
            fgEscSeq[colorName] = ( (cmd | getline escSeq) > 0 ? escSeq : "<" colorName ">" )
            close(cmd)

            cmd = "tput setab " colorNr
            bgEscSeq[colorName] = ( (cmd | getline escSeq) > 0 ? escSeq : "<" colorName ">" )
            close(cmd)
        }

        cmd = "tput sgr0"
        colorOff = ( (cmd | getline escSeq) > 0 ? escSeq : "<sgr0>" )
        close(cmd)

        highlight["Today"]    = bgEscSeq["BLACK"]  fgEscSeq["WHITE"]
        highlight["Holiday"]  = bgEscSeq["RED"]    fgEscSeq["YELLOW"]
        highlight["Birthday"] = bgEscSeq["CYAN"]   fgEscSeq["RED"]
        highlight["Meeting"]  = bgEscSeq["YELLOW"] fgEscSeq["GREEN"]
        highlight[""]         = bgEscSeq["GREEN"]  fgEscSeq["WHITE"]

        tgtDates[today] = "Today"
    }
    NR==FNR {
        tgtDates[$1" "$2] = $3
        next
    }
    NF == 3  { split($0,months); print; next } # month list
    !/[0-9]/ { print; next }            # blank line or days list
    {                                   # dates list
        for ( mthNr=1; mthNr<=3; mthNr++ ) {
            mthName   = months[mthNr]
            inDayNrs  = substr($0,1,20)
            outDayNrs = ""
            while ( match(inDayNrs,/[0-9]+/) ) {
                inDayNr   = substr(inDayNrs,RSTART,RLENGTH)
                curDate   = mthName " " inDayNr
                highlightOn = highlightOff = ""
                if ( curDate in tgtDates ) {
                    dateType = tgtDates[curDate]
                    highlightOn = ( dateType in highlight ? highlight[dateType] : highlight[""] )
                    highlightOff = colorOff
                }
                outDayNr  = highlightOn inDayNr highlightOff
                outDayNrs = outDayNrs substr(inDayNrs,1,RSTART-1) outDayNr
                inDayNrs  = substr(inDayNrs,RSTART+RLENGTH)
            }
            printf "%s   ", outDayNrs inDayNrs
            $0 = substr($0,24)
        }
        print ""
    }
' "$1" -

在此输入图像描述

答案2

感谢这个 awk 脚本。这很棒,但我必须做一些小的调整才能使其在 Ubuntu 中运行。我已经在 Ubuntu 20.04.4 LTS 和 18.04.6 LTS 中成功测试了它。

所做的更改是:(采用新旧格式的差异)

2c2
< cal 2022 |
---
> ncal -bh 2022 |
55,56c55,56
<             printf "%s   ", outDayNrs inDayNrs
<             $0 = substr($0,24)
---
>             printf "%s  ", outDayNrs inDayNrs
>             $0 = substr($0,23)

为简单起见,修订如下:

#!/usr/bin/env bash
ncal -bh 2022 |
awk -v today="$(date +'%B %-d')" '
    BEGIN {
        split("BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE",tputColors)
        for (i in tputColors) {
            colorName = tputColors[i]
            colorNr = i-1

            cmd = "tput setaf " colorNr
            fgEscSeq[colorName] = ( (cmd | getline escSeq) > 0 ? escSeq : "<" colorName ">" )
            close(cmd)

            cmd = "tput setab " colorNr
            bgEscSeq[colorName] = ( (cmd | getline escSeq) > 0 ? escSeq : "<" colorName ">" )
            close(cmd)
        }

        cmd = "tput sgr0"
        colorOff = ( (cmd | getline escSeq) > 0 ? escSeq : "<sgr0>" )
        close(cmd)

        highlight["Today"]    = bgEscSeq["BLACK"]  fgEscSeq["WHITE"]
        highlight["Holiday"]  = bgEscSeq["RED"]    fgEscSeq["YELLOW"]
        highlight["Birthday"] = bgEscSeq["CYAN"]   fgEscSeq["RED"]
        highlight["Meeting"]  = bgEscSeq["YELLOW"] fgEscSeq["GREEN"]
        highlight[""]         = bgEscSeq["GREEN"]  fgEscSeq["WHITE"]

        tgtDates[today] = "Today"
    }
    NR==FNR {
        tgtDates[$1" "$2] = $3
        next
    }
    NF == 3  { split($0,months); print; next } # month list
    !/[0-9]/ { print; next }            # blank line or days list
    {                                   # dates list
        for ( mthNr=1; mthNr<=3; mthNr++ ) {
            mthName   = months[mthNr]
            inDayNrs  = substr($0,1,20)
            outDayNrs = ""
            while ( match(inDayNrs,/[0-9]+/) ) {
                inDayNr   = substr(inDayNrs,RSTART,RLENGTH)
                curDate   = mthName " " inDayNr
                highlightOn = highlightOff = ""
                if ( curDate in tgtDates ) {
                    dateType = tgtDates[curDate]
                    highlightOn = ( dateType in highlight ? highlight[dateType] : highlight[""] )
                    highlightOff = colorOff
                }
                outDayNr  = highlightOn inDayNr highlightOff
                outDayNrs = outDayNrs substr(inDayNrs,1,RSTART-1) outDayNr
                inDayNrs  = substr(inDayNrs,RSTART+RLENGTH)
            }
            printf "%s  ", outDayNrs inDayNrs
            $0 = substr($0,23)
        }
        print ""
    }
' "$1" -

相关内容