如何通过读取命令解析sh的cal输出?

时间:2018-05-08 11:28:22

标签: linux shell unix sh

我正在尝试编写一个脚本,该脚本将打印指定年份$3中的所有月份,该日期在$1(例如Mo,Tu,...)中的某一天在同一日期打印$2(1,2,3,...)。

实施例: 输入:./task1.sh Tu 5 2006

输出:

September 2006
Mo Tu We Th Fr Sa Su
            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

December 2006
Mo Tu We Th Fr Sa Su
            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

我写过这个剧本:

#!/bin/sh
year=$3
dayInMonth=$2
dayInWeek=$1

index=1

while expr $index '!=' 13 >/dev/null; do
  cal -m $index $year| tail -n +2| while read Mo Tu We Th Fr Sa Su ; do
    eval theDay='$'$dayInWeek
    if [ "$theDay" = "$dayInMonth" ]; then
      cal -m $index $year;
    fi
  done
  index=$(expr $index + 1)
done

但是读取第三行校准输出存在问题。在这些行中,天数通常不会在Mo处开始。如何解析第三行校准输出,以便$Mo$Tu$We,...中的数字始终正确?

我需要POSIX标准友好解决方案。

2 个答案:

答案 0 :(得分:2)

更新:您已添加了posix一致性解决方案的要求。我的回答中使用的date -d不符合POSIX。我将为那些使用GNU / Linux的人保留答案。

顺便说一句,以下命令可以正确地纠正2006年1月5日的星期偏移:

cal 01 2006 | awk -v d=5 'NR>2{for(i=1;i<NF;i++){if($i==d){print i;exit}}}'

你需要修改一个小的shell脚本。

我会使用date命令,如下所示:

#!/bin/bash
dayofweek="${1}"
day="${2}"
year="${3}"

for m in {01..12} ; do
    date=$(LANG=C date -d "${year}-${m}-${day}" +'%a %B')
    read d m <<< "${date}"
    [ "${d}" = "${dayofweek}" ] && echo "${m}"
done

结果:

$ bash script.sh Thu 05 2006
January
October

答案 1 :(得分:0)

使用命令date检查日期会更容易。

for month in {1..12}; do 
  if [[ $(date -d $(printf "%s-%2.2d-%2.2d" "$year" "$month" "$day") "+%a") == "Tue" ]]; then 
    cal -m $month $year; 
  fi
done

脚本在12个月内循环,并根据年和日生成日期。 date命令以+%a输出3字母格式的日期。

如果您希望以数字格式显示星期几,请在+%u声明中使用== 2if