Как получить последние 'N' рабочих дней в скрипте оболочки Unix с помощью цикла `for`?

Как получить последние 'N' рабочих дней в скрипте оболочки Unix с помощью цикла `for`?

Следующий скрипт:

N=5
BUSINESS_DATE=`date -d "-2 day" +"%Y%m%d"`
for (( c=0; c<N ; c++ ))
do
    WEEKDAY=`date --date="$BUSINESS_DATE -$c day" +%w`

    if [ $WEEKDAY == "0" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day-2day" +%Y%m%d`;
    elif [ $WEEKDAY == "6" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day -2day" +%Y%m%d`;
    elif [ $WEEKDAY == "5" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day -2day" +%Y%m%d`;
    elif [ $WEEKDAY == "4" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day -2day" +%Y%m%d`;
    elif [ $WEEKDAY == "3" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day -2day" +%Y%m%d`;
    elif [ $WEEKDAY == "2" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day -2day" +%Y%m%d`;
    elif [ $WEEKDAY == "1" ]
    then
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day -2day" +%Y%m%d`;
    else
        FILE_DT_TMP=`date --date="$BUSINESS_DATE -$c day" +%Y%m%d`
    fi
    export FILE_DT=$FILE_DT_TMP
    echo "File date is :$FILE_DT"
done

не выдает надлежащий вывод. Может ли кто-нибудь подсказать мне – что не так и как это исправить?

решение1

Если вам нужно всего 5 рабочих дней до сегодняшнего дня, попробуйте:

for d in Mon Tue Wed Thu Fri
do
    date +%Y%m%d -d "last $d"
done | sort

За любые N дней до сегодняшнего дня:

N=10
for i in $(seq $(($N + $N / 5 * 2)) -1 1)
do
    [ `date --date="-$i day" +%u` -le 5 ] &&
       date -d "-$i day" +"File date is : %Y%m%d"
done

решение2

Я понимаю, что вы на самом деле хотите указать N дней, а не жестко заданные пять, которые вы указали в своем вопросе. Вот bashрешение, которое удовлетворит это требование:

n=5
today=$(date +'%Y-%m-%d')
for ((d=1; n>0; d++))
do
    # Adjust this next line to get the date format you require, e.g. +'%Y%m%d'
    date=$(date --date "$today -$d day")
    nday=$(date --date "$today -$d day" +'%w')
    if [[ nday > 0 && nday < 6 ]]
    then
        # Adjust this next line to output whatever you really need
        echo "n=$n, d=$d, nday=$nday, date=$date: WEEKDAY"
        ((n--))
    fi
done

Вывод для n=5, запущен 5 ноября 2015 г.

n=5, d=1, nday=3, date=Wed,  4 Nov 2015 00:00:00: WEEKDAY
n=4, d=2, nday=2, date=Tue,  3 Nov 2015 00:00:00: WEEKDAY
n=3, d=3, nday=1, date=Mon,  2 Nov 2015 00:00:00: WEEKDAY
n=2, d=6, nday=5, date=Fri, 30 Oct 2015 00:00:00: WEEKDAY
n=1, d=7, nday=4, date=Thu, 29 Oct 2015 00:00:00: WEEKDAY

решение3

Когда я применяю эти изменения к вашему скрипту:

1c1
< BUSSINESS_DATE=date -d "-2 day" +"%Y%m%d"
---
> BUSSINESS_DATE=$(date -d "-2 day" +"%Y%m%d")
5c5
<     WEEKDAY=date --date="$BUSSINESS_DATE -$c day" +%w
---
>     WEEKDAY=$(date --date="$BUSSINESS_DATE -$c day" +%w)

Я получаю такой вывод:

File date is :20151101
File date is :20151031
File date is :20151030
File date is :20151029
File date is :20151028

Это то, что вы ищете?

решение4

Ого, это совершенно нечитаемо. Попробуйте использовать case-оператор вместо if/then/elif/else/fi.

например

BUSSINESS_DATE=$(date -d "-2 day" +"%Y%m%d")
for (( c=0; c<5 ; c++ )) ; do
    WEEKDAY=$(date --date="$BUSSINESS_DATE -$c day" +%w)

    case "$WEEKDAY" in
        0) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day-2day" +%Y%m%d) ;;
        6) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day -2day" +%Y%m%d) ;;
        5) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day -2day" +%Y%m%d) ;;
        4) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day -2day" +%Y%m%d) ;;
        3) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day -2day" +%Y%m%d) ;;
        2) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day -2day" +%Y%m%d) ;;
        1) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day -2day" +%Y%m%d) ;;
        *) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day" +%Y%m%d) ;;
    esac    

    export FILE_DT=$FILE_DT_TMP
    echo "File date is :$FILE_DT"
done

Обратите внимание, что переформатирование текста для удобства чтения также делает очевидным отсутствие пробела между dayи -2dayна 0корпусе. Это легко исправить.

    0) FILE_DT_TMP=$(date --date="$BUSSINESS_DATE -$c day-2 day" +%Y%m%d) ;;

Кстати, на вашем месте я бы сделал имена переменных намного короче (и, возможно, добавил бы комментарий перед первым их использованием, чтобы четко обозначить их назначение), чтобы сделать скрипт еще более читабельным, избегая переносов строк.

например, измените BUSINESS_DATE на BD

# BD is Business Date
BD=$(date -d "-2 day" +"%Y%m%d")

FILE_DT_TMPможно переименовать в FDT, и FILE_DTв FDили FDATE.

BD=$(date -d "-2 day" +"%Y%m%d")
for (( c=0; c<5 ; c++ )) ; do
    WEEKDAY=$(date --date="$BD -$c day" +%w)

    case "$WEEKDAY" in
        0) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        6) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        5) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        4) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        3) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        2) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        1) FDT=$(date --date="$BD -$c day -2day" +%Y%m%d) ;;
        *) FDT=$(date --date="$BD -$c day" +%Y%m%d) ;;
    esac    

    FDATE="$FDT"
    echo "File date is : $FDATE""
done

Такое переформатирование кода имеет реальное преимущество: когда элементы, которые должны быть выстроены в ряд, не выстраиваются в ряд, они выделяются, как мигающая неоновая вывеска.

Другие примечания:

  1. Я заменил все обратные кавычки на $(). Обратные кавычки устарели и портят кавычки, не используйте их.

  2. Нет необходимости экспортировать FILE_DT (он же FDATE) - переменная будет потеряна, когда подоболочка, в которой она запущена, завершится. Она будет установлена ​​в родительской оболочке, только если вы используете скрипт с . scriptname.

Связанный контент