使用 bash 中的 cal 函数挑选“第一个”日期

使用 bash 中的 cal 函数挑选“第一个”日期

我试图从cal函数和管道awk命令中挑选出第一个星期一、第二个星期二、第二个星期六等。这个月我可以获得第一个星期二正确使用日历下面的命令:

    December 2018
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

>cal | awk 'NF == 7 && NR > 2 {print $3; exit}'
>4

但这并不总是有效,请参阅下面 2016 年 3 月的测试:

     March 2016
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

>cal 3 2016 | awk 'NF == 7 && NR > 2 {print $3; exit}'
>8

为什么它适用于顶部示例而不适用于底部示例?我认为底部的示例应该查看第三行并找到 的正确结果1。有没有一种万无一失的方法可以使用awk- 也许检查该列是否为空并移动到下一行来获取这些日期?

答案1

这是为您提供的另一个解决方案

cal | awk 'NR >= 3 { tu = substr($0,7,2) +0 } tu { print tu; exit }'
4

cal 3 2016 | awk 'NR >= 3 { tu = substr($0,7,2) +0 } tu { print tu; exit }'
1

它挑选出星期二列(字符 7 和 8),并提供第一个非零值。该方法可以安全地推断到一周中的任何一天。

答案2

使用 GNU 日期:

对于当月的第一个星期二:

for day in 0{1..7}; do [[ "$(date -d $(date +%Y%m${day}) +%a)" = "Tue" ]] && echo "$day";done

对于给定年份和月份的第一个星期二:

year=2016
month=03
for day in 0{1..7}; do [[ "$(date -d ${year}${month}${day} +%a)" = "Tue" ]] && echo "$day";done

awk 中的“星期二”变体:

cal | awk -F "" '!/[[:alpha:]]/ && $7$8 ~ /[0-9]/ { print $7$8;exit }'

这将检查输出中第 7 列和第 8 列(星期二)的硬编码位置(请注意,字段分隔符为空,将输入拆分为每个字符)——在跳过任何包含字母的行(标题行)之后。调整 7 和 8 以获得其他日期。

为了更清楚地显示上一个命令正在执行的操作,awk 命令的字段按列编号:

123456789            <--- awk fields $1, $2, $3, ... $9
    December 2018
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

答案3

gcal(GNU) 和(BSD) 系列都ncal支持转置行与列的选项:

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

$ gcal -i

March 2024

Sunday          3 10 17 24 31
Monday          4 11 18 25   
Tuesday         5 12 19 26   
Wednesday       6 13 20 27   
Thursday        7 14 21 28   
Friday       1  8 15 22 29   
Saturday     2  9 16 23 30   

当以这种方式调用时,可以更轻松地按星期几选择顺序位置。首先使用awk模式匹配所需的一周中的某一天,然后打印 N-1 列以获取一周中该天的第 N 个实例。

例如,特定月份和年份的第一个星期二:

$ ncal 12 2018 | awk '/^Tu/ { print $2; }'
4
$ ncal 3 2016 | awk '/^Tu/ { print $2; }'
1

要获取当月的第 5 个星期五(恰好有一个):

$ ncal | awk '/^Fr/ { print $6; }’
29

答案4

在 ksh93 中:

$ printf '%(%F)T\n' 'first monday this month'
2024-03-04
$ printf '%(%F)T\n' 'second tuesday this month'
2024-03-12
$ printf '%(%F)T\n' '2nd tuesday in 2016-03'
2016-03-08

(注意第 4、5 个在当前版本的 ksh93u+m 中不起作用; fourthfifth尽管如此)。

相关内容