如何在Unix中填充零填充的一个月内的第一个周二捕获

时间:2015-03-16 07:14:03

标签: date unix awk sed

@Unix

我试图将每个月的第一个周二捕获到一个变量中,并试图在没有运气的情况下对其进行填充。

以下是我正在尝试的代码:

cal | sed -e 's/ \([1-9]\) /0\1 /g' -e 's/ \([1-9]\)$/0\1/' | awk 'NR>2{Sfields=7-NF; if (Sfields == 0 ) {printf "%d\n",$3;exit}}'

有人可以帮助我,我在这里缺少什么吗?

4 个答案:

答案 0 :(得分:1)

# for monday calendar
cal -m1 | sed -n '1,2b;/^.\{3\} \{0,1\}\([0-9]\{1,2\}\) .*/ {s//0\1/;s/.*\([0-9]\{2\}\)$/\1/p;q;}'
# for sunday calendar
cal -s1 01 01 2015 | sed -n '1,2b;/^.\{6\} \{0,1\}\([0-9]\{1,2\}\) .*/ {s//0\1/;s/.*\([0-9]\{2\}\)$/\1/p;q;}'
  • cal选项取决于系统(在Red Hat 6.6上进行测试),并表示-m表示星期一作为第一天,-s表示星期日(附加1表示1个月的展示)。根据您指定的cal输出行。
  • 默认情况下不打印
  • 不关心第1行和第2行
  • 采用非空第二(/第三)组
  • 取第二个(/第三个)数字组(位置)直到下一个并替换为0,删除trailng char
  • 取第一组的最后一位数字,删除其余部分并打印
  • 退出(没有其他行)

感谢@Jotne关于第二周(第4行而不是第3周)第一天和第一天的第一天的所有评论

答案 1 :(得分:1)

awk应该:

cal | awk 'NR>2 && NF>4 {printf "%02d\n",$(NF-4);exit}'
03

确认其工作:

for i in {1..12}; do cal -m $i | awk 'NR>2 && NF>4 {printf "%02d\n",$(NF-4);exit}' ; done
06
03
03
07
05
02
07
04
01
06
03
01

或者您可以使用ncal

ncal | awk '/Tu/ {printf "%02d\n",$2}'
03

如果您喜欢可以指定星期名称的版本,
并且如果Monday是一周的第一天,那么这个gnu awk应该这样做:

cal | awk 'NR==2 {for (i=1;i<=NF;i++) {sub(/ /,"",$i);a[$i]=i}} NR>2 {if ($a["Tu"]~/[0-9]/) {printf "%02d\n",$a["Tu"];exit}}' FIELDWIDTHS="3 3 3 3 3 3 3 3"
03

它使用FIELDWITH来确保月初的空列不会更改输出。

答案 2 :(得分:0)

我想我得到了答案。

cal | awk 'NR>2{Sfields=7-NF; if (Sfields == 0 ) {printf "%02d\n",$3;exit}}' 

上述陈述可以。"%02d"为我做了

答案 3 :(得分:0)

bash和日期。可能比解析cal慢:

y=2015
for m in {1..12}; do
    for d in {01..07}; do
        if [[ $(date -d "$y-$m-$d" +%w) -eq 2 ]]; then
            echo $d
            break
        fi
    done
done

转换为awk:会更快,因为它不必多次调用日期:

gawk -v y=2015 '
    BEGIN {
        for (m=1; m<=12; m++) {
            for (d=1; d<=7; d++) {
                t = mktime( y " " m " " d " 12 0 0" )
                if (strftime("%w", t) == 2) {
                    printf "%02d\n", d
                    break
                }
            }
        }
    }
'