In #! / Bin / bash. Unix-Befehl zum Abrufen des Datums des ersten Wochentags eines Monats

8

Ich suche nach direkten Unix-Befehlen, um den ersten Sonntag des nächsten Monats, den ersten Montag des nächsten Monats, den ersten Dienstag des nächsten Monats, den ersten Mittwoch des nächsten Monats usw. zu erhalten.

  1. Ich werde sie im vollständigen Datumsformat benötigen (Zeit ist nicht obligatorisch)

  2. Ich kann Zahlen wie 2, 3, 4 usw. erhalten. Da ich nicht nur Zahlen möchte, benötige ich sie im Datumsformat (einschließlich Tag, Monat, Jahr).

    $ NEXT_MONTH=`date +'%m %Y' -d 'next month'`
    $ echo $NEXT_MONTH
    04 2017
    
    $ NEXT_SUNDAY=`cal $NEXT_MONTH | awk 'NF==7 && !/^Su/{print $1;exit}'`
    $ echo $NEXT_SUNDAY
    2
  3. Ich benötige diese Daten, um Benachrichtigungen für die E-Mail-Gruppe zu senden.

Beispiel: Ich könnte den ersten Samstag im nächsten Monat wie folgt bekommen.

$ firstofmonth=$(date -d '+1 months' '+%Y%m01')
20170401

$ firstsaturday=$(date -d "$firstofmonth" '+%Y-%m')-$((7 - \
                $(date -d "$firstofmonth" '+%u')     ))    
2017-04-1
Hima
quelle

Antworten:

11

In ksh93:

$ printf '%(%F)T\n' 'next month, first Monday'
2017-04-03

bash, da 4.2 jetzt ein %(<format)Tin seinem printfBuitin unterstützt, aber nicht die Fähigkeit, diese Art von Datumsausdruck zu analysieren.

Wenn Sie das verwenden müssten bashund wollten %(<format>)T, könnten Sie es trotzdem tun, ohne sich mit etwas wie:

printf -v code '%(
  t=$((%s + (12 - %-H) * 60 * 60))
  increment=$((8 - %u))
  current_month=%m)T' -1
eval "$code"
until
  t=$((t + increment * 24 * 60 * 60)) # next Monday around mid-day
  printf -v code '%(date=%F month=%m)T' "$t"
  eval "$code"
  [ "$month" != "$current_month" ] # until be get to next month
do
  increment=7 # the first increment is the number of days
              # til Monday. Next increments are just a week.
done
echo "$date"
Stéphane Chazelas
quelle
#! / bin / bash. Ich erhalte den folgenden Fehler in bash $ printf '% (% F) T \ n' 'nächsten Monat, erster Montag' -bash: printf: `(': ungültiges Formatzeichen
Hima
1
@ Hima, ich habe in ksh93 gesagt . bashist ein unvollendeter Klon von ksh (mit einigen Merkmalen von (t) csh und zsh und sogar einigen eigenen). Neuere Versionen von bashhaben Unterstützung für printf '%(format)T'von hinzugefügt ksh93, aber nicht die Möglichkeit, diese Art von Datumsspezifikationen zu analysieren. Ersetzen Sie Ihre Knall durch #! /path/to/ksh93 -.
Stéphane Chazelas
" bashist ein unvollendeter Klon von ksh" - ich habe mich immer so gefühlt.
Tim Kennedy
@Stephene, ich habe mit dem folgenden Befehl versucht, nächsten Monat letzten Samstag $ cal 04 2017 | zu bekommen awk 'NF <= 7 {print $ 6}' | grep -v "^ $" | tail -1 28 Es zeigt die Nummer 28 an, aber ich suche nach dem vollständigen Datum 28.04.2017, bitte schlagen Sie vor, wenn es damit möglich ist.
Hima
9

Angenommen, GNU date(dafür verwenden -dSie sich selbst) und eine zshähnliche Shell für {1..7}:

$ for i in {1..7} ; do \
    LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
  done | awk '/Mon/ {print $1}'
2017-04-03

Ersetzen Sie das awk Mondurch einen beliebigen Wochentag (verwenden Sie LC_ALL=Cdiese Option, um englische Monatsnamen unabhängig vom Gebietsschema des Benutzers abzurufen). Es ist möglicherweise auch besser, dies in einer Variablen zu speichern, wenn Sie für jeden Wochentag eine neue Abfrage durchführen:

$ days=$(for i in {1..7} ; do \
           LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
         done)

$ for i in Mon Tue Wed Thu Fri Sat Sun ; do \
    echo "${days}" | awk "/${i}/"'{print $1}' ; \
  done
2017-04-03
2017-04-04
2017-04-05
2017-04-06
2017-04-07
2017-04-01
2017-04-02
Parkamark
quelle
In Bash gibt dieser Code auch den nächsten Monat zuerst zurück. So, Mo, Mi, So, Fr, Sa. Vielen Dank. Ich denke, ich kann diesen Befehl ändern, um nächsten Monat letzten Sonntag, Montag, Mittwoch usw. zu erhalten. Lassen Sie mich dies versuchen.
Hima
Hallo, ich habe den folgenden Befehl versucht, um nächsten Monat letzten Samstag $ cal 04 2017 | zu erhalten awk 'NF <= 7 {print $ 6}' | grep -v "^ $" | tail -1 Es zeigt die Nummer 28 an, aber ich suche nach dem vollständigen Datum wie 28.04.2017, bitte schlagen Sie vor, wenn es möglich ist.
Hima
"für i in {1..7}; Datum '+% Y-% m-% d% a' -d" $ (Datum +% Y% m01 -d '2 Monate') $ {i} Tage zuvor "; done | awk '/ Sat / {print $ 1}'" - dies ergibt den 29.04.2017, den letzten Samstag des nächsten Monats. Dieser Code läuft 2 Monate vorwärts bis zum ersten Tag dieses Monats und dann 1-7 Tage zurück, um die Daten der letzten 7 Tage für den Vormonat abzurufen. Ich persönlich würde die Verwendung von cal vermeiden, da ich die anderen Beispiele hier ausprobiert habe und bei meiner Version (CentOS 6) überhaupt keine funktioniert.
Parkamark
2

PHP macht es eigentlich ziemlich einfach, Daten mit Texteingabe zu analysieren, wenn es auf Ihrem System verfügbar ist.

Beispiel:

bash-[522]$ php -qr 'date_default_timezone_set("UTC"); echo date("d-m-Y\n", strtotime("first monday of next month"));'
03-04-2017

Ich habe diese Funktion in meiner .bashrc:

get_date ()
{
    text="$*";
    php -qr "date_default_timezone_set(\"UTC\"); echo date(\"d-m-Y\n\", strtotime(\"$text\"));"
}

Was ich verwenden kann als:

bash-[523]$ get_date first monday of next month
03-04-2017

Bearbeiten Hinzufügen der zu verwendenden Optioncal

Fast jedes System, das hat, bashwird haben cal. Das Kalenderprogramm. Sie können eine Liste des Termins für die ersten jede Woche Tages erhalten , indem eine Kombination aus Laufen cal, dateund awk, wie folgt:

 cal -hN $(date -d 'next month' +%b' '%Y) | grep -v $(date -d 'next month' +%b) | awk -v date=$(date -d 'next month' +%Y-%m-) '{ printf "%s: "date"%02i\n", $1, $2; }'

Welches gibt Ihnen die folgende Ausgabe:

Su: 2017-04-02
Mo: 2017-04-03
Tu: 2017-04-04
We: 2017-04-05
Th: 2017-04-06
Fr: 2017-04-07
Sa: 2017-04-01

Ändern $2zu $NFin der awk - Anweisung den Zeitpunkt des letzten Auftretens eines jeden Tages in einem Monat zu bekommen.

Tim Kennedy
quelle
Es funktioniert nicht in Bash, $ php -qr 'date_default_timezone_set ("UTC"); Echodatum ("dmY \ n", strtotime ("erster Montag des nächsten Monats")); ' -bash: php: Befehl nicht gefunden. Bitte lassen Sie mich wissen, wie ich es auch in Bash erledigen kann. und auch der Befehl, nächsten Monat letzten Sonntag bis Samstag zu bekommen. Ich habe es versucht, einige, wie es Fehler wirft. Vielen Dank ..!!
Hima
Das heißt, Sie haben nicht phpinstalliert. Ich habe mit einem Beispiel aktualisiert, die verwendet cal, dateund awkBefehle.
Tim Kennedy
Ich habe diesen Befehl ausprobiert und einen Fehler ausgegeben. Vielen Dank.!! $ cal -hN $ (Datum -d 'nächster Monat' +% b ''% Y) | grep -v $ (Datum -d 'nächster Monat' +% b) | awk -v Datum = $ (Datum -d 'nächster Monat' +% Y-% m-) '{printf "% s:" Datum "% 02i \ n", $ 1, $ 2; } 'cal: ungültige Option - h Verwendung: cal [-13smjyV] [[Monat] Jahr]
Hima