毎月の最終勤務日

毎月の最終勤務日
#!/bin/bash
#!/usr/local/bin
#!/usr/sbin
#!/usr/bin
# Script to Check last working Day of the Month

echo " Enter Month and Year :"
read mon year
cal $mon $year| egrep  "28|29|30|31"|awk 'BEGIN {
        var1=$NF;var2=NF;
        }
        {
        if (NF > 1 &&  NF < 7)
                val=$NF;
        else if (NF == 1)
                val=$NF-2;
        else if (NF == 7)
                val=$NF-1;
        }
        {
                print "Last Working Date is : " val;
        }'

スクリプト出力:

511@ubuntu:~/Unix$ ./test.sh
 Enter Month and Year :
4 2015
Last Working Date is : 30
511@ubuntu:~/Unix$ ./test.sh
 Enter Month and Year :
5 2015
Last Working Date is : 29
Last Working Date is : 29
511@ubuntu:~/Unix$ ./test.sh
 Enter Month and Year :
7 2015
Last Working Date is : 31
511@ubuntu:~/Unix$ ./test.sh
 Enter Month and Year :
1 2015
Last Working Date is : 30

次のように入力すると、スクリプトが2回印刷されるのはなぜですか?

511@ubuntu:~/Unix$ ./test.sh
 Enter Month and Year :
5 2015
Last Working Date is : 29
Last Working Date is : 29

答え1

問題は、egrep「28」、「29」、「30」、または「31」が表示される各行に対して検索が1回呼び出されることです。検索基準に一致する2行があるため、awk最後の週より前の28日間の月は2回呼び出されます。awk

常に検索の2行目を使用したいので、コマンドを使用して最後の行のみを表示egrepできtailます。

#!/bin/bash
#!/usr/local/bin
#!/usr/sbin
#!/usr/bin
# Script to Check last working Day of the Month

echo " Enter Month and Year :"
read mon year
cal $mon $year| egrep  "28|29|30|31"| tail -n 1 |awk 'BEGIN {
        var1=$NF;var2=NF;
        }
        {
        if (NF > 1 &&  NF < 7)
                val=$NF;
        else if (NF == 1)
                val=$NF-2;
        else if (NF == 7)
                val=$NF-1;
        }
        {
                print "Last Working Date is : " val;
        }'

答え2

日付の場合は、bash計算の2行だけが必要です。

#!/bin/bash

month="$1"
year="$2"

read -r dow day < <(date -d "$year/$month/1 +1 month -1 day" "+%u %d")

echo "Last working day of the month = $(( day - ( (dow>5)?(dow-5):0 ) ))"

計算方法は次のとおりです。ダウ(曜日)が5より大きい場合はその日付から(ダウ-5)を減算し、そうでない場合は曜日を変更せずに保持します。

使用:

$ ./script 2 2015
Last working day of the month = 27

答え3

そしてksh93

$ printf "%(%A %B %d)T\n" "October 2018 last working day"
Wednesday October 31

答え4

awkはegrepから2行を受け取るので、スクリプトは繰り返し印刷されます。しかし、これは他の答えで扱われました。

問題をより短く簡単に解決できるいくつかの代替方法を説明したいと思います。

これが呼び出されると、プログラムcalは月曜日から始まる週を印刷します(これは数学を単純化します)cal -NMC month year。それを書く:

#!/bin/bash

    lastday(){
        printf 'Last Working Date of %s/%s = ' "$1" "$2";
        cal -NMC "$1" "$2" | awk '
            /[0-9]+/{val=$( NF>5?5:NF )}
            END{ print val }'
    }

mon="$1"
year="$2"
lastday "$mon" "$year"

説明する:

/[0-9]+/数字のある行を選択してください(空白行は避けてください)。

NF>5?5:NF数学:フィールドが5より大きい場合、結果は5、そうでない場合はNFです。

{val=$( ... )}フィールドの値を選択します。

END{ print val }'最後の行(数値のある行)の値のみを印刷します。

次のように呼び出します。

$ ./test.sh 4 2015
Last Working Date of 4/2015 = 30
$ ./test.sh 5 2015
Last Working Date of 5/2015 = 29
$ ./test.sh 7 2015
Last Working Date of 7/2015 = 31
$ ./test.sh 1 2015
Last Working Date of 1/2015 = 30
$ ./test.sh 9 2015
Last Working Date of 9/2015 = 30
$

関連情報