Shell/ksh脚本特定日期查询功能故障求助
Shell日期查询脚本问题排查与修复
需求概述
需要实现两种日期查询功能:
- 接收星期几(支持缩写/完整名,如Mon/Monday)和天数,输出过去该天数范围内所有对应星期几的日期;
- 接收星期范围(如Mon-Wed)和周数,输出过去该周数范围内,每周对应星期区间内的每一天日期。
原脚本代码
#!/bin/bash read -p "Enter 1 to enter a weekday and number of past days or 2 to enter a weekday range and number of weeks: " option case "$option" in 1) read -p "Enter a weekday (Monday, Tuesday, etc.): " day read -p "Enter number of past days: " days start_time="00:00:00" end_time="24:00:00" for (( i=0; i<=$days; i++ )); do date=$(date --date="$i days ago" +%Y%m%d) day_of_week=$(date --date="$i days ago" +%A) if [ "$day_of_week" == "$day" ]; then echo "Date: $date $start_time, End time: $date $end_time" fi done ;; 2) read -p "Enter a weekday range (e.g. Mon to Wed): " range read -p "Enter number of weeks: " weeks start_time="00:00:00" end_time="24:00:00" range_array=($(echo $range | tr '-' ' ')) start_weekday=${range_array[0]} end_weekday=${range_array[-1]} for (( i=0; i<=$((weeks*7)); i++ )); do date=$(date --date="$i days ago" +%Y%m%d) day_of_week=$(date --date="$i days ago" +%A) if [ "$day_of_week" == "$start_weekday" ]; then start_date=$date elif [ "$day_of_week" == "$end_weekday" ]; then end_date=$date echo "Start date: $start_date $start_time, End date: $end_date $end_time" fi done ;; *) echo "Invalid input" exit 1 ;; esac
问题排查
功能1的问题
- 星期格式不兼容:脚本用
%A获取完整星期名(如Monday),但用户可能输入缩写(如Mon),导致匹配失败; - 重复调用
date命令:每次循环两次调用date,冗余且效率低; - 循环范围歧义:
i<=days会包含今天(i=0),不符合“过去N天”的常规理解(通常不含当天)。
功能2的问题
- 输入处理逻辑混乱:提示示例是
Mon to Wed,但脚本用tr '-' ' '处理减号,用户输入Mon to Wed会被分割为Mon、to、Wed,导致end_weekday取值错误; - 星期格式不兼容:同样存在完整名与缩写不匹配的问题;
- 核心逻辑错误:当前脚本仅记录区间首尾日期并输出组合,未实现“输出范围内每一天的日期”的需求;
- 循环范围逻辑错误:
weeks*7的循环范围未考虑星期区间的跨周问题,且未按需求遍历输出对应区间的每一天。
修复后的脚本
#!/bin/bash # 统一星期转换函数:将输入的星期(缩写/完整名)转为数字(1=周一,7=周日) get_weekday_num() { local input_day=$1 # 处理完整名和缩写,忽略大小写 case "${input_day,,}" in mon|monday) echo 1 ;; tue|tuesday) echo 2 ;; wed|wednesday) echo 3 ;; thu|thursday) echo 4 ;; fri|friday) echo 5 ;; sat|saturday) echo 6 ;; sun|sunday) echo 7 ;; *) echo "Invalid weekday" >&2; exit 1 ;; esac } read -p "输入1查询指定星期的历史日期,输入2查询星期区间的历史日期:" option case "$option" in 1) read -p "输入星期几(支持缩写/完整名,如Mon/Monday):" day read -p "输入查询的过去天数:" days start_time="00:00:00" end_time="24:00:00" target_num=$(get_weekday_num "$day") # 从1开始循环,排除今天,查询过去days天内的日期 for (( i=1; i<=$days; i++ )); do # 一次获取日期和星期数字,减少冗余调用 read -r date_str weekday_num <<< $(date --date="$i days ago" +"%Y%m%d %u") if [ "$weekday_num" -eq "$target_num" ]; then echo "日期: $date_str $start_time, 结束时间: $date_str $end_time" fi done ;; 2) read -p "输入星期范围(格式如Mon-Wed):" range read -p "输入查询的过去周数:" weeks start_time="00:00:00" end_time="24:00:00" # 用减号分割星期范围,正确解析首尾星期 IFS='-' read -r start_day end_day <<< "$range" start_num=$(get_weekday_num "$start_day") end_num=$(get_weekday_num "$end_day") # 计算总查询天数:过去weeks周,即weeks*7天前到昨天 total_days=$((weeks * 7)) for (( i=1; i<=$total_days; i++ )); do read -r date_str weekday_num <<< $(date --date="$i days ago" +"%Y%m%d %u") # 判断当前星期是否在区间内,支持跨周日的情况(如Fri-Sun) if [ "$start_num" -le "$end_num" ]; then if [ "$weekday_num" -ge "$start_num" ] && [ "$weekday_num" -le "$end_num" ]; then echo "日期: $date_str $start_time, 结束时间: $date_str $end_time" fi else if [ "$weekday_num" -ge "$start_num" ] || [ "$weekday_num" -le "$end_num" ]; then echo "日期: $date_str $start_time, 结束时间: $date_str $end_time" fi fi done ;; *) echo "无效输入" exit 1 ;; esac
修复说明
- 新增星期转换函数:支持缩写和完整名输入,统一转为星期数字(1-7),彻底解决格式匹配问题;
- 优化
date调用:一次获取日期和星期数字,减少冗余系统调用; - 功能1逻辑调整:循环从1开始,排除今天,符合“过去N天”的常规理解;
- 功能2输入处理:用
IFS='-'正确分割Mon-Wed格式的范围,修复输入解析错误; - 功能2核心逻辑修复:支持跨周日的星期区间判断,输出区间内每一天的日期,完全符合需求;
- 交互优化:调整为中文提示,更贴合国内使用习惯。
内容的提问来源于stack exchange,提问作者abhishek
相关产品推荐
相关产品推荐

