简体   繁体   English

如何在 shell 脚本 (.sh,.ksh) 中查找日期

[英]How to find dates in shell script (.sh,.ksh)

i want to take input from user 1. enter weekday(eg. mon,tue..) and number of days 2. enter a range of weekdays (eg. mon-wed) and the number of weeks我想从用户那里获取输入 1. 输入工作日(例如周一、周二..)和天数 2. 输入工作日范围(例如周一至周三)和周数

if he enters 1 and gives mon and 30 so I want in output, dates of each Monday who came in past 30 days如果他输入 1 并给出 mon 和 30,那么我想在 output 中输入过去 30 天内每个星期一的日期

if he enters mon-wed and the number of weeks 5 then we want dates of Mon, Tue, wed of past 5 weeks如果他输入 mon-wed 和周数 5 那么我们想要过去 5 周的周一、周二、周三的日期

I wrote a script but it's not giving me and expected output can anyone please help me我写了一个脚本,但它没有给我预期的 output 谁能帮帮我


#!/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

Perhaps something like this也许是这样的

read -p "Enter a weekday (Monday, Tuesday, etc.): " day
read -p "Enter number of past days: " days
for n in $(seq 0 7 $days); do
    date -d"last-${day}-${n} days" +%Y%m%d
done

which gives you the list of all the days, like它给你所有日子的清单,比如

20230123
20230116
20230109
20230102
20221226
20221219
20221212
20221205
20221128

for (today) and Monday and 60 .对于(今天)和Monday60

The logic of your original script did not capture the essence of your problem definition .原始脚本的逻辑没有捕捉到问题定义的本质

This adaptation of your script offers both command line specification or menu-based selection .脚本的这种改编提供了命令行规范基于菜单的选择 NOTE: some values were hard-coded to simplify the testing ( you only need to swap the comment between associated pairs of lines in a few places ).注意:一些值是硬编码的以简化测试(您只需要在几个地方交换相关行对之间的注释)。

#!/bin/bash

DBG=0

error()
{
    echo -e "\n ERROR: missing parameter for '${opt}' option."
    errors
}

error2()
{
    echo -e "\n Invalid options on command line."
    errors
}

errors()
{
    echo -e "\n Only options allowed:\n\t [ --days {day_of_week} {day_range} | --weeks {dow_range} {week_range} ].\n Bye!\n" ; exit 1
}

pSel=1
while [ $# -gt 0 ]
do
    case $1 in
        --days )
            opt=$1
            option=1
            if [ $# -lt 3 ] ; then error ; fi 
            match_DOWn="$2" ; days="$3" ; shift ; shift ; shift
            pSel=0
            ;;
        --weeks )
            opt=$1
            option=2
            if [ $# -lt 3 ] ; then error ; fi 
            range="$2" ; weeks="$3" ; shift ; shift ; shift
            pSel=0
            ;;
        * ) error2 ;;
    esac
done


if [ ${pSel} -eq 1 ]
then
    echo -e " Enter selection:\n\t 1 (to enter a weekday and number of past days) \n or\t 2 (to enter a weekday range and number of weeks)\n => \c" >&2 ; read option <&2
fi

today_DOWi=`date '+%u' `
today_DOWn=`date '+%a' `
today_DATE=$(date '+%Y%m%d' )


if [ ${DBG} -eq 1 ]
then
    echo "About Today:"
    echo ${today_DOWi}
    echo ${today_DOWn}
    echo ${today_DATE}
    echo ""
fi

declare -a weekdays=( "Dummy:0" "Mon:1" "Tue:2" "Wed:3" "Thu:4" "Fri:5" "Sat:6" "Sun:7" )

reportDayOfWeekName()
{
    i=0
    while [ ${i} -lt 8 ]
    do
        #echo ${weekdays[${i}]} >&2
        if [[ ${weekdays[${i}]} =~ ${match_DOWi} ]] ; then break ; fi
        i=$((i+=1)) ;
    done
    echo "${weekdays[${i}]}" | cut -f1 -d\:
}

reportDayOfWeekIndex()
{
    i=0
    while [ ${i} -lt 8 ]
    do
        #echo ${weekdays[${i}]} >&2
        if [[ ${weekdays[${i}]} =~ ${match_DOWn} ]] ; then break ; fi
        i=$((i+=1)) ;
    done
    echo "${weekdays[${i}]}" | cut -f2 -d\:
}


start_time="00:00:00"
end_time="24:00:00"


case "${option}" in
    1)
        if [ -z "${match_DOWn}" ]
        then
            #read -p "Enter a weekday (Monday, Tuesday, etc.): " match_DOWn
            match_DOWn=Mon

            #read -p "Enter number of past days: " days
            days=28
        fi

        #-----------------------------------------------------
        adjust=$(( $(reportDayOfWeekIndex) - ${today_DOWi} ))
        if [ ${adjust} -gt 0 ]
        then
            adjust=$((adjust-=7))
        fi

        first=$(date --date "${today_DATE} + ${adjust} days" '+%Y%m%d' )
        test ${DBG} -eq 1 && echo "First = " ${first} >&2
        #-----------------------------------------------------

        first=$(date --date "${today_DATE} + ${adjust} days" '+%Y%m%d' )
        date=${first}

        test ${DBG} -eq 1 && echo "LAST = " $((days + ${adjust})) >&2

        i=0
        while [ ${i} -le $((days + ${adjust})) ]
        do
            echo "Date: ${date} ${start_time}, End time: ${date} ${end_time}"
            date=$(date --date "${date} - 7 days" '+%Y%m%d' )
            i=$((i+=7))
        done
        ;;
    2)
        if [ -z "${range}" ]
        then
            #read -p "Enter a weekday range (e.g. Mon to Wed): " range
            range="Mon-Tue"

            #read -p "Enter number of weeks: " weeks
            weeks=3
        fi

        match_DOW_F=`echo "${range}" | cut -f1 -d\- `
        test ${DBG} -eq 1 && echo "match_DOW_F = ${match_DOW_F}" >&2

        match_DOW_L=`echo "${range}" | cut -f2 -d\- `
        test ${DBG} -eq 1 && echo "match_DOW_L = ${match_DOW_L}" >&2

        #-----------------------------------------------------
        match_DOWn=${match_DOW_F}

        dowF=$(reportDayOfWeekIndex)
        test ${DBG} -eq 1 && echo "dowF = ${dowF}" >&2

        adjustFST=$((${dowF} - ${today_DOWi} ))
        if [ ${adjustFST} -gt 0 ]
        then
            adjustFST=$((adjustFST-=7))
        fi

        first=$(date --date "${today_DATE} + ${adjustFST} days" '+%Y%m%d' )
        test ${DBG} -eq 1 && echo "First = " ${first} >&2

        #-----------------------------------------------------
        match_DOWn=${match_DOW_L}

        dowL=$(reportDayOfWeekIndex)
        test ${DBG} -eq 1 && echo "dowL = ${dowL}" >&2

        #-----------------------------------------------------
        date=${first}
        j=1
        while [ ${j} -le ${weeks} ]
        do
            test ${DBG} -eq 1 && echo "j = " ${j} >&2
            dateHOLD=${date}

            i=$((dowF))
            while [ ${i} -le $((dowL)) ]
            do
                test ${DBG} -eq 1 && echo "i = " ${i} >&2
                echo "Date: ${date} ${start_time}, End time: ${date} ${end_time}"
                date=$(date --date "${date} + 1 day" '+%Y%m%d' )
                i=$((i+=1))
            done
            date=$(date --date "${dateHOLD} - 1 week" '+%Y%m%d' )
            echo ""
            j=$((j+=1))
        done
        ;;
    "" )
        echo -e "\n No selection. Bye!\n"
        exit 0
        ;;
    *)
        echo -e "\n Invalid selection."
        errors
        exit 1
        ;;
esac

The output for option 1 is as follows:选项1的output如下:

 Enter selection:
     1 (to enter a weekday and number of past days) 
 or  2 (to enter a weekday range and number of weeks)
 => 1
Date: 20230123 00:00:00, End time: 20230123 24:00:00
Date: 20230116 00:00:00, End time: 20230116 24:00:00
Date: 20230109 00:00:00, End time: 20230109 24:00:00
Date: 20230102 00:00:00, End time: 20230102 24:00:00

The output for option 2 is as follows:选项2的output如下:

 Enter selection:
     1 (to enter a weekday and number of past days) 
 or  2 (to enter a weekday range and number of weeks)
 => 2
Date: 20230123 00:00:00, End time: 20230123 24:00:00
Date: 20230124 00:00:00, End time: 20230124 24:00:00

Date: 20230116 00:00:00, End time: 20230116 24:00:00
Date: 20230117 00:00:00, End time: 20230117 24:00:00

Date: 20230109 00:00:00, End time: 20230109 24:00:00
Date: 20230110 00:00:00, End time: 20230110 24:00:00

Also note: This script does not incorporate the logic to "normalize" random format of the input (ie mon or MON vs expected Mon).另请注意:此脚本不包含“规范化”输入随机格式的逻辑(即 mon 或 MON 与预期的 Mon)。 You would likely need to incorporate an awk function to do that.您可能需要合并 awk function 才能做到这一点。

I suggest you consider the following guidance.我建议您考虑以下指导。

If you start by writing the code logic如果您从编写代码逻辑开始

  • in pseudo-code,在伪代码中,
  • fine-grained for each task that you are trying to accomplish,对您要完成的每项任务进行细粒度处理,
  • in the correct sequence and以正确的顺序和
  • in the correct context,在正确的上下文中,

then having that worded so that it does exactly what you want it to do... will, almost explicitly , tell you WHAT you need to code for each of those, not the HOW .然后使用该措辞,使其完全按照您的意愿执行...将几乎明确地告诉您您需要为每个代码编写什么,而不是如何编写代码。 The HOW is the nitty gritty of coding. HOW是编码的本质。

What you have provided above in your question does not reflect the necessary separation of logical elements or details to address the required task breakdown.您在上面的问题中提供的内容并未反映逻辑元素或细节的必要分离以解决所需的任务分解。

If you give that a try, the solution will almost pop out of the page at you.如果您尝试一下,解决方案几乎会从您的页面中弹出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM