Último dia útil do mês

2
#!/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;
        }'

Saída de script:

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

Alguém por favor pode ajudar porque o script é impresso duas vezes enquanto nós damos uma entrada como abaixo:

511@ubuntu:~/Unix$ ./test.sh
 Enter Month and Year :
5 2015
Last Working Date is : 29
Last Working Date is : 29
    
por Aashish Raj 22.08.2015 / 18:11

6 respostas

1

O problema é que a sua pesquisa egrep vai chamar awk uma vez para cada linha que vir "28", "29", "30" ou "31". Os meses em que o dia 28 chegar antes da última semana do calendário terão awk chamados duas vezes, pois duas linhas correspondem aos seus critérios de pesquisa

Você deseja sempre usar a segunda linha da pesquisa egrep , para poder usar o comando tail para ver apenas a última linha:

#!/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;
        }'
    
por 22.08.2015 / 18:48
1

Com data, é apenas um cálculo bash de duas linhas:

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

A matemática é: se dow (o dia da semana) for maior que 5, subtraia (dow-5) do dia, senão, deixe o dia inalterado.

Use como:

$ ./script 2 2015
Last working day of the month = 27
    
por 28.08.2015 / 04:09
1

com ksh93 :

$ printf "%(%A %B %d)T\n" "October 2018 last working day"
Wednesday October 31
    
por 20.06.2018 / 10:26
0

Seu script depende da saída de tela de cal . Para fazer as coisas de maneira mais adequada, você pode usar o comando date :

#!/bin/bash
# Calculates the last working day (Mon-Fri) of the month

echo "Enter Month and Year:"
read month year
lastdom='date -d "$year/$month/1 + 1 month - 1 day" "+%d"'
dow='date -d "$year/$month/1 + 1 month - 1 day" "+%u"'

if [ $dow -ge 6 ] 
then 
        lastwdom=$(($lastdom - $dow + 5))
else
        lastwdom=$(($lastdom))
fi

echo "Last working day is $lastwdom"
    
por 24.08.2015 / 11:44
0

Seu script repete a impressão porque o awk está recebendo duas linhas do egrep. Mas isso já foi abordado em outras respostas.

Eu quero explicar algumas formas alternativas de resolver o problema, mais curtas e mais fáceis.

A calibração do programa pode imprimir a semana a partir de segunda-feira (o que simplifica a matemática) quando chamada como cal -NMC month year . Usando isso:

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

Descrição:

/[0-9]+/ Selecione linhas com números (evite linha vazia).

NF>5?5:NF Math: Se mais campos do que 5 resultarem em 5, mais NF.

{val=$( ... )} Selecione o valor do campo.

END{ print val }' Imprime apenas o valor da última linha (linha com números).

Chame assim:

$ ./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
$
    
por 25.08.2015 / 03:09
0
read -p "Please enter date 'yyyymmdd':" dat
yy='echo $dat|cut -c 1-4'
mm='echo $dat|cut -c 5-6'

case $mm in

01|02|03)
mm=12
yy='expr $yy - 1'
dd='cal $mm $yy|awk -F " " '{print $6}'|grep -v ^$|tail -1'
echo $yy$mm$dd
;;

04|05|06)
mm=03
dd='cal $mm $yy|awk -F " " '{print $6}'|grep -v ^$|tail -1'
echo $yy$mm$dd
;;

07|08|09)
mm=06
dd='cal $mm $yy|awk -F " " '{print $6}'|grep -v ^$|tail -1'
echo $yy$mm$dd
;;

10|11|12)
mm=09
dd='cal $mm $yy|awk -F " " '{print $6}'|grep -v ^$|tail -1'
echo $yy$mm$dd
;;

*) echo "Invalid month"
exit;;
esac
    
por 20.06.2018 / 10:13