编写POSIX兼容Shell脚本:查询指定年份中日期匹配的月份并输出月历
编写POSIX兼容Shell脚本:查找指定年份中符合条件的月份
我来帮你完成这个POSIX兼容的Shell脚本,刚好能满足你要的需求——找出指定年份里,当月第N天是指定星期的所有月份,并打印它们的月历信息。
需求回顾
你需要的脚本接收三个参数:
$1:星期缩写(比如Mo、Tu)$2:当月的日期(比如5)$3:目标年份(比如2006)
示例输入:./task1.sh Tu 5 2006,输出2006年9月、12月的月历。
完整POSIX兼容脚本
#!/bin/sh # 检查参数数量是否正确 if [ $# -ne 3 ]; then echo "用法: $0 <星期缩写> <日期> <年份>" echo "示例: $0 Tu 5 2006" exit 1 fi target_weekday="$1" target_day="$2" year="$3" # 定义cal命令输出的星期缩写顺序(对应列索引0-6) weekday_list="Su Mo Tu We Th Fr Sa" # 查找目标星期对应的列索引(转换为0-based) target_index=$(echo "$weekday_list" | tr ' ' '\n' | grep -n "^$target_weekday$" | cut -d: -f1) if [ -z "$target_index" ]; then echo "错误:无效的星期缩写,请使用以下格式之一:Su, Mo, Tu, We, Th, Fr, Sa" exit 1 fi target_index=$((target_index - 1)) # 遍历1-12月 for month in $(seq 1 12); do # 获取该月的日期行(过滤cal的标题和空行) date_lines=$(cal "$month" "$year" | grep -E '^[ 0-9]+$') # 检查每一行日期,匹配目标日期和星期列 echo "$date_lines" | while read -r line; do # 将行拆分为数组,每个元素对应一个星期列的日期 day_columns=($line) # 如果目标日期在对应星期的列上,打印月历 if [ "${day_columns[$target_index]}" = "$target_day" ]; then echo "=== $year年$month月 ===" cal "$month" "$year" echo "" break # 找到后跳出当前月份的循环 fi done done
关键逻辑说明
- 参数校验:先确保用户输入了正确数量的参数,否则给出清晰的用法提示。
- 星期列匹配:通过解析
cal命令的星期头,把用户输入的星期缩写映射到对应的列索引(比如Tu对应第2列,索引为2)。 - 月份遍历:对每个月份,提取
cal输出的日期行,检查目标日期是否出现在指定的星期列中。如果匹配,就打印该月的完整月历。 - POSIX兼容性:全程使用POSIX标准命令(
cal、grep、tr、seq等),避免了GNU专属的date -d这类扩展,确保在所有POSIX兼容的Shell环境中都能运行。
测试示例
运行命令:
./task1.sh Tu 5 2006
输出结果会是:
=== 2006年9月 === September 2006 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 === 2006年12月 === December 2006 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
内容的提问来源于stack exchange,提问作者Přemysl Šťastný
相关产品推荐
相关产品推荐

