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" -

関連情報