Wie erhält man die letzten ‚N‘ Werktage in einem Unix-Shell-Skript mithilfe einer ‚for‘-Schleife?

Wie erhält man die letzten ‚N‘ Werktage in einem Unix-Shell-Skript mithilfe einer ‚for‘-Schleife?

Das folgende Skript:

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

gibt keine korrekte Ausgabe aus. Kann mir jemand sagen, was falsch ist und wie ich das Problem beheben kann?

Antwort1

Wenn Sie nur 5 Werktage vor heute möchten, versuchen Sie:

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

Für alle N-Tage vor heute:

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

Antwort2

Ich verstehe, dass Sie eigentlich N Tage aufgelistet haben möchten und nicht die fest codierten fünf, die Sie in Ihrer Frage angegeben haben. Hier ist eine bashLösung, die diese Anforderung erfüllt:

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

Ausgabe für n=5, ausgeführt am 5. November 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

Antwort3

Wenn ich diese Änderungen auf Ihr Skript anwende:

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)

Ich erhalte diese Ausgabe:

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

Ist es das, wonach Sie suchen?

Antwort4

Wow, das ist außerordentlich unlesbar. Versuchen Sie, eine Case-Anweisung anstelle von if/then/elif/else/fi zu verwenden.

z.B

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

Beachten Sie, dass durch die Neuformatierung zur besseren Lesbarkeit auch das fehlende Leerzeichen zwischen dayund deutlich wird. -2dayDas 0lässt sich leicht beheben.

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

Übrigens würde ich an Ihrer Stelle die Variablennamen viel kürzer machen (und vielleicht vor ihrer ersten Verwendung einen Kommentar hinzufügen, um klar anzugeben, was sie sind), um das Skript durch Vermeidung von Zeilenumbrüchen noch lesbarer zu machen.

Ändern Sie beispielsweise BUSINESS_DATE in BD

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

FILE_DT_TMPFDTkönnte in , und FILE_DTin FDoder umbenannt werden 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

Das Neuformatieren von Code auf diese Weise bietet einen echten Vorteil: Wenn Dinge, die eigentlich übereinstimmen sollten, nicht übereinstimmen, fällt dies wie ein blinkendes Neonschild auf.

Weitere Hinweise:

  1. Ich habe alle Backticks in geändert $(). Backticks sind veraltet und bringen die Anführungszeichen durcheinander. Verwenden Sie sie nicht.

  2. Es besteht keine Notwendigkeit, FILE_DT (auch FDATE genannt) zu exportieren – die Variable geht verloren, wenn die Sub-Shell, in der sie ausgeführt wird, beendet wird. Sie wird nur dann in der übergeordneten Shell festgelegt, wenn Sie das Skript mit als Quelle verwenden . scriptname.

verwandte Informationen