使用 ncal 或 cal 以某种格式显示周数

k0p*_*kus 23 command-line bash terminal calendar

当两个命令每个都做你想做的一件事但都不做时,你难道不喜欢它吗?

这就是cal它的作用。格式不错。虽然缺少周数:

$ cal
    January 2012      
Su Mo Tu We Th Fr Sa  
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30 31              
Run Code Online (Sandbox Code Playgroud)

这就是ncal它的作用。奇怪的格式,但有周数:

$ ncal -w
    January 2012      
Su  1  8 15 22 29   
Mo  2  9 16 23 30   
Tu  3 10 17 24 31   
We  4 11 18 25      
Th  5 12 19 26      
Fr  6 13 20 27      
Sa  7 14 21 28      
    1  2  3  4  5   
Run Code Online (Sandbox Code Playgroud)

我想要的那种输出,实际上是cal和之间的杂交ncal -w

$ cal --magik-calendar-week-option
      January 2012      
   Su Mo Tu We Th Fr Sa  
1   1  2  3  4  5  6  7  
2   8  9 10 11 12 13 14  
3  15 16 17 18 19 20 21  
4  22 23 24 25 26 27 28  
5  29 30 31
Run Code Online (Sandbox Code Playgroud)

slm*_*slm 19

如果这两个命令都不适合您的需要,您可以使用它gcal来代替您做您想做的事。

例子

$ gcal -K

      April 2014
 Su Mo Tu We Th Fr Sa CW
        1  2  3  4  5 13
  6  7  8  9 10 11 12 14
 13 14 15 16 17 18 19 15
 20 21 22 23 24 25 26 16
 27 28 29 30          17
Run Code Online (Sandbox Code Playgroud)

在右侧最后一列中打印周数。

参考


Pet*_*r.O 10

这会突出显示今天的日期,并且可以通过$1以下形式显示任何月份:YYYY-mm-dd... 默认为今天的日期

它被设置为显示 ISO 周数,第一个工作日是星期一。

#!/bin/bash
# Input reference date is expected in  'YYYY-mm-dd' format
#
today=($(date '+%Y %m %d')); Y=0; m=1; d=2                # establish today's date
[[ -z $1 ]] && ref=(${today[@]}) || ref=(${1//-/ })       # get input date
dNbA=$(date --date="$(date +%Y-%m-01)" +'%u')             # day-number of 1st day of reference month
today[m]=$((10#${today[m]})); ref[m]=$((10#${ref[m]}))    # remove leading zero (octal clash)
today[d]=$((10#${today[d]})); ref[d]=$((10#${ref[d]}))    # remove leading zero (octal clash)
nxtm=$(( ref[m]==12 ?1       :ref[m]+1 ))                 # month-number of next month
nxtY=$(( ref[m]==12 ?ref[Y]+1:ref[Y]   ))                 # year-number of next month
nxtA="$nxtY-$nxtm-1"                                      # date of 1st day of next month
refZ=$(date --date "$(date +$nxtA) yesterday" +%Y-%m-%d)  # date of last day of reference  month
days=$(date --date="$refZ" '+%d')                         # days in reference month

h1="$(date --date="${ref[Y]}-${ref[m]}-${ref[d]}" '+%B %Y')" # header 1 
h2="Mo Tu We Th Fr Sa Su"                                    # header 2 
printf "    %$(((${#h2}-${#h1}-1)/2))s%s\n" " " "$h1"
printf "    %s\n" "$h2"
# print week rows   
printf "%2d  " "$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-01)" +'%V')))" # week-number (of year) with suppressed leading 0
printf "%$(((dNbA-1)*3))s"  # lead spaces (before start of month)
dNbW=$dNbA  # day-number of week
dNbM=1      # day-number of month
while ((dNbM <= days)) ;do
    if (( today[Y]==ref[Y] &&  
          today[m]==ref[m] && 
          today[d]==dNbM )) ;then
        printf "\x1b[7m%2d\x1b[0m " "$dNbM" # highlight today's date 
    else
        printf "%2d " "$dNbM"
    fi
    ((dNbM++))
    if ((dNbW  >=7)) ;then
        cdate=$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-$dNbM)" +'%V'))) # remove leading zero (octal clash)
        printf "\n%2d  " "$cdate" # week-number of year
        dNbW=0
    fi
    ((dNbW++))
done
printf "%$(((8-dNbW)*3))s\n" # trailing spaces (after end of month)
Run Code Online (Sandbox Code Playgroud)

这是本月的显示(20突出显示)

       January 2012
    Mo Tu We Th Fr Sa Su
52                     1 
 1   2  3  4  5  6  7  8 
 2   9 10 11 12 13 14 15 
 3  16 17 18 19 20 21 22 
 4  23 24 25 26 27 28 29 
 5  30 31                
Run Code Online (Sandbox Code Playgroud)


ang*_*gus 7

您可以使用nl对行进行编号(这就是程序的目的:)。但是您需要从某个地方提取当月的第一周。它可以从ncal自己完成:

$ ncal -w 2 2012 | tail -1 | awk '{print $1}'
5
Run Code Online (Sandbox Code Playgroud)

我们将其作为参数插入nl's 选项-v(起始行号),并告诉它只对带有数字或空格的行进行编号。

$ cal 2 2012 | nl -bp'^[0-9 ]\+$' -w2 -s'  ' -v$(ncal -w 2 2012 | tail -1 | awk '{print $1}')
       February 2012
    Su Mo Tu We Th Fr Sa
 5            1  2  3  4
 6   5  6  7  8  9 10 11
 7  12 13 14 15 16 17 18
 8  19 20 21 22 23 24 25
 9  26 27 28 29
Run Code Online (Sandbox Code Playgroud)

然而,这一切都非常脆弱。无论如何,如果您不需要cal更高级的选项,它会起作用。您可以将它放在一个文件中并替换"$@"我放置的位置2 2012


编辑:但这是错误的!我刚刚注意到一月的第一周可能有 52 或 53 个数字!因此,我们要么必须为 1 月设置一个例外,要么只需从中提取所有周数ncal并将其应用于cal.

这是我最初想到的解决方案,但我认为(错误地)我会使用nl. 它使用paste, 并排合并文件。由于没有任何文件,我们必须使用 bashism <(...);这就是我试图避免的。

我们的第一个“文件”将是周数列表,开头有两个空行:

$ printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)


52
 1
 2
 3
 4
 5
Run Code Online (Sandbox Code Playgroud)

第二个,只是cal. 总之,作为参数paste

$ paste -d' ' <(printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)) <(cal 1 2011)
        January 2011
    Su Mo Tu We Th Fr Sa
52                     1
 1   2  3  4  5  6  7  8
 2   9 10 11 12 13 14 15
 3  16 17 18 19 20 21 22
 4  23 24 25 26 27 28 29
 5  30 31
Run Code Online (Sandbox Code Playgroud)

比另一个更混乱和不相容。终...


fun*_*let 7

生成周序列ncalpaste用于并排两个输出。

$ paste <(echo; echo; ncal -w | tail -1 | xargs -n1 printf '%2d\n') <(cal)
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢将制表符作为分隔符,只需添加类似 sed 's/\t/ /'


编辑:方式更简单,无需关心标签:

$ paste -d' ' <((echo -n '   '; ncal -w | tail -1 )| fold -w 3) <(cal)
Run Code Online (Sandbox Code Playgroud)