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
if he enters 1 and gives mon and 30 so I want in output, dates of each Monday who came in past 30 days
if he enters mon-wed and the number of weeks 5 then we want dates of Mon, Tue, wed of past 5 weeks
I wrote a script but it's not giving me and expected output can anyone please help me
#!/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
CodePudding user response:
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
.
CodePudding user response:
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:
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:
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 (i.e. mon or MON vs expected Mon). You would likely need to incorporate an awk function to do that.
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.
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.