Jak korzystać z zapytania If-Else na podstawie dnia tygodnia?


10

Problem: Muszę sprawdzić, czy dzisiaj jest czwartek i wykonać różne działania w zależności od wyniku tego warunku. Próbowałem dwóch różnych podejść:

Uzyskiwanie nazwy dnia:

DAYOFWEEK=$(date +"%a")
echo DAYOFWEEK: $DAYOFWEEK
if ["$DAYOFWEEK" == "Thu"]; 
then   
   echo YES
else
    echo NO
fi

Uzyskiwanie numeru dnia:

DAYOFWEEK=$(date +"%u")
echo DAYOFWEEK: $DAYOFWEEK

if ["$DAYOFWEEK" == 4]; 
then
   echo YES
else
   echo NO
fi

W obu przypadkach dane wyjściowe są NIE, mimo że powinny być TAK. Co jest nie tak?


1
Dodatkowa uwaga: ;byłyby one wymagane, gdybyś miał thentę samą linię if. W tym przypadku są zbędne.
manatwork

Odpowiedzi:


12

Problemem jest brakujące puste miejsce.

Poniższy kod będzie działał w powłokach, których [wbudowane polecenie akceptuje ==jako alias =:

if [ "$DAYOFWEEK" == 4 ];  then    echo YES; else    echo NO; fi

Pamiętaj jednak (patrz help testw bash):

  • ==nie jest oficjalnie wspomniany, należy użyć =do porównania ciągów
  • -eqjest przeznaczony do dziesiętnych testów arytmetycznych (nie zrobi tu różnicy, date +%uale date +%dna przykład przy porównywaniu 04i 4które są liczbowo takie same, ale leksykalnie różne).

Wolałbym:

 if [ "${DAYOFWEEK}" -eq 4 ];  then    echo YES; else    echo NO; fi

Zasadniczo powinieneś preferować metodę liczby dni , ponieważ ma ona mniejszą zależność od bieżących ustawień regionalnych . W moim systemie produkcja date +"%a"jest dzisiaj Do.


3

Nie przeocz, casektóry często jest lepszym sposobem na zrobienie tego rodzaju rzeczy:

Uważaj również, że wynik działania date +%azależy od ustawień regionalnych, więc jeśli spodziewasz się angielskich nazw, skrypt przestanie działać po wywołaniu na przykład przez użytkownika francuskiego lub koreańskiego.

case $(LC_ALL=C date +%a) in
   (Mon) echo first day of the week;;
   (Thu) do-something;;
   (Sat|Sun) echo week-end;;
   (*) echo any other day;; # last ;; not necessary but doesn't harm
esac

Zauważ, że powyżej jest jednym z rzadkich przypadków, w których $(...)nie trzeba go cytować (chociaż cytaty nie zaszkodzą. Tak samo jak w var="$(...)").


0

W tym samym pomyśle używam następującego fragmentu kodu, aby „wyłączyć” crona przed wybraną godziną.
Oczywiście wolałbym zmodyfikować sam crontab ... gdybym uzyskał niezbędne uprawnienia :)

Oto prosty test, który przerywa skrypt bash, chyba że jesteśmy w nocy.

# Delay or restrict execution.
# Here, we quit unless hour is greater than (gt) 2 and (-a) lower than (lt) 7
# i.e. execution happens only at 3,4,5&6 o'clock.
if  /usr/bin/test `date '+%H'` -gt 2 -a `date '+%H'` -lt 7; then
  echo LETS_START_PROCESSING;
else
  exit;
fi

#Put job here

Po co używać /usr/bin/testzamiast wbudowanego [polecenia powłoki ?
Stéphane Chazelas

@ Stéphane Chazelas Nie korzystałem z 3,4,5,6, ponieważ nie mam dostępu do crontab. ( jest to druga linia mojego postu :) Naszymi serwerami zarządza Claranet, a my już straciliśmy tydzień ping-ponga, aby uzyskać ... działającego crona (nie żartuję). Dlatego unikamy bałaganu i ponownego otwierania biletów, kiedy możemy :) Z tego powodu poprosiliśmy o croniczne zadanie cron zamiast codziennie, a dopóki wszystkie nasze testy nie zostaną zakończone, łatwiej będzie nie dotykać zadania, i dodaj nasze elementy sterujące do wykonanego skryptu.
Balmipour

Ach, OK, przepraszam, myślałem, że masz na myśli, że nie masz prawa modyfikować cronpliku wykonywalnego w przeciwieństwie do pliku crontab użytkownika.
Stéphane Chazelas

@ Stéphane Chazelas Jeśli chodzi o składnię testową, wolałem ją od [] lub [[]], ponieważ najpierw wypróbowałem skrypt na innym serwerze, na którym mogłem użyć crontab. Po zbyt wielu niespodziankach z cronami, przyzwyczaiłem się używać ścieżki absolutnej tak często, jak to możliwe. Można powiedzieć, że powoduje to, że testy są brzydkie i będą miały rację ... ale odpowiem, że testy powłoki są zawsze brzydkie i też będą miały rację ^^ Najważniejsze było dla mnie uzyskanie odpowiedzi, która działałaby proste kopiowanie / wklejanie i dołączanie wyjaśnień.
Balmipour,

1
Zauważ, że -ajest przestarzałe w test. Standardowo użyłbyś : hour=$(date +%H); if [ "$hour" -gt 2 ] && [ "$hour" -lt 7 ](lub hour=`date +%H`gdybyś musiał być kompatybilny z powłoką Bourne'a, czyli Solaris 10 i starszymi, a może obecnie rzadkimi jednorożcami SCO)
Stéphane Chazelas

0

Aby zatrzymać skrypt w dniu tygodnia, usuń tylko wiersz dnia:

DAYOFWEEK=$(date +"%u")
echo "$DAYOFWEEK";
if [ "$DAYOFWEEK" == 1 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 2 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 3 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 4 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 5 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 6 ]; then exit; else echo; fi
if [ "$DAYOFWEEK" == 7 ]; then exit; else echo; fi

Witamy w Unix SE! Nie jestem pewien, czy poprawnie zrozumiałem twój pierwszy wiersz. Czy nie byłoby if [ "$DAYOFWEEK" -lt 7 ]lepiej?
peterh - Przywróć Monikę

-1

Po pierwsze, powinieneś zacytować zadanie DAYOFWEEK = "$ (data +% u)"

I musisz mieć spacje po każdej stronie nawiasów [i].

Średnik na końcu linii jest zbędny.


1
Cytowanie nie jest potrzebne.
H.-Dirk Schmitt

Aby rozwinąć komentarz @ H.-DirkSchmitt: powodem, dla którego cytowanie nie jest potrzebne, jest to, że dane wyjściowe nie będą zawierać spacji.
CVn

@ MichaelKjörling: Nie - nigdy nie jest potrzebny ;-) Wypróbuj przykład:a=$(echo 1 2 3); echo $a;
H.-Dirk Schmitt

@ H.-DirkSchmitt a=$(echo "1 2 3"); echo $az wieloma spacjami między cyframi (StackExchange nie pozwoli mi uczynić go prostym kopiowaniem i wklejaniem, niestety).
CVn,

@ MichaelKjörling - patrz man bash „Jeśli podstawienie pojawia się w podwójnych cudzysłowach, w wynikach nie są wykonywane dzielenie słów i rozwijanie nazw ścieżek”. Tak więc w przypadku pytania i przykładu „1 2 3” nie ma różnicy.
H.-Dirk Schmitt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.