it-swarm.com.de

Suchdatum in Bash

Wie würden Sie ein Datum in bash mit separaten Feldern (Jahre, Monate, Tage, Stunden, Minuten, Sekunden) in verschiedene Variablen parsen?

Das Datumsformat lautet: YYYY-MM-DD hh:mm:ss

48
Steve

Muss es bash sein? Sie können die coreutils /bin/date-Binärdatei GNU für viele Transformationen verwenden:

 $ date --date="2009-01-02 03:04:05" "+%d %B of %Y at %H:%M and %S seconds"
 02 January of 2009 at 03:04 and 05 seconds

Dadurch wird das angegebene Datum analysiert und im ausgewählten Format angezeigt. Sie können das beliebig an Ihre Bedürfnisse anpassen.

60

Dies ist einfach, konvertieren Sie einfach Ihre Bindestriche und Doppelpunkte in ein Leerzeichen (IFS muss nicht geändert werden) und verwenden Sie "read" in einer Zeile:

read Y M D h m s <<< ${date//[-:]/ }

Zum Beispiel:

$ date=$(date +'%Y-%m-%d %H:%M:%S')
$ read Y M D h m s <<< ${date//[-: ]/ }
$ echo "Y=$Y, m=$m"
Y=2009, m=57
26
NVRAM

Ich hatte ein anderes Eingabezeitformat, daher gibt es hier eine flexiblere Lösung. 

Datumsangaben in BSD/macOS umrechnen

date -jf in_format [+out_format] in_date

wo die Formate strftime verwenden (siehe man strftime ).

Für das angegebene Eingabeformat YYYY-MM-DD hh:mm:ss:

$ date -jf '%Y-%m-%d %H:%M:%S' '2017-05-10 13:40:01'
Wed May 10 13:40:01 PDT 2017

Um sie in separate Variablen einlesen zu können, nehme ich die Idee des NVRAM an, erlaube Ihnen jedoch, jedes Strftime-Format zu verwenden:

$ date_in='2017-05-10 13:40:01'

$ format='%Y-%m-%d %H:%M:%S'

$ read -r y m d H M S <<< "$(date -jf "$format" '+%Y %m %d %H %M %S' "$date_in")"

$ for var in y m d H M S; do echo "$var=${!var}"; done
y=2017
m=05
d=10
H=13
M=40
S=01

(In Skripten immer immer use read -r .)

In meinem Fall wollte ich zwischen Zeitzonen konvertieren (die Zonennamen finden Sie in Ihrem /usr/share/zoneinfo-Verzeichnis):

$ format=%Y-%m-%dT%H:%M:%S%z

$ TZ=UTC date -jf $format +$format 2017-05-10T02:40:01+0200
2017-05-10T00:40:01+0000

$ TZ=America/Los_Angeles date -jf $format +$format 2017-05-10T02:40:01+0200
2017-05-09T17:40:01-0700

Datumsangaben in GNU/Linux konvertieren

Auf einem Mac können Sie die GNU - Version von date als gdate mit brew install coreutils installieren.

date [+out_format] -d in_date

wo das out_format strftime verwendet (siehe man strftime ). 

Im Befehl GNU coreutils date gibt es keine Möglichkeit, ein Eingabeformat explizit festzulegen, da es versucht, das Eingabeformat von selbst herauszufinden, und Dinge funktionieren normalerweise einfach. (Für Details lesen Sie das Handbuch unter coreutils: Datumseingabeformate .)

Zum Beispiel:

$ date '+%Y %m %d %H %M %S' -d '2017-05-10 13:40:01'
2017 05 10 13 40 01

Um sie in separate Variablen einlesen zu können, ändern Sie den Befehl im Mac-Abschnitt, indem Sie den Befehl in der Klammer durch die Version GNU ersetzen.

Um zwischen Zeitzonen zu konvertieren (Zonennamen finden Sie im /usr/share/zoneinfo-Verzeichnis), können Sie TZ="America/Los_Angeles" rechts in Ihrer Eingabezeichenfolge angeben. Beachten Sie die Literalzeichen " um den Zonennamen und das Leerzeichen vor in_date:

TZ=out_tz date [+out_format] 'TZ="in_tz" 'in_date

Zum Beispiel:

$ format='%Y-%m-%d %H:%M:%S%z'

$ TZ=America/Los_Angeles date +"$format" -d 'TZ="UTC" 2017-05-10 02:40:01'
2017-05-09 19:40:01-0700

$ TZ=UTC date +"$format" -d 'TZ="America/Los_Angeles" 2017-05-09 19:40:01'
2017-05-10 02:40:01+0000

GNU date versteht auch Stundenversätze für die Zeitzone:

$ TZ=UTC date +"$format" -d '2017-05-09 19:40:01-0700'
2017-05-10 02:40:01+0000
8
$ t='2009-12-03 12:38:15'
$ a=(`echo $t | sed -e 's/[:-]/ /g'`)
$ echo ${a[*]}
2009 12 03 12 38 15
$ echo ${a[3]}
12
7
DigitalRoss

Die Array-Methode ist vielleicht besser, aber genau darum haben Sie gefragt:

IFS=" :-"
read year month day hour minute second < <(echo "YYYY-MM-DD hh:mm:ss")
4
Steve Baker

anstatt das Shell-Skript zu verwenden, fügen Sie es wie unten beschrieben in Ihr Skript ein, wann immer Sie möchten:

a=date +%Y 
b=date +%S
c=date +%H

a wird Jahr sein b wird Sekunden sein c wird Stunden sein. und so weiter.

3
Vijay

Pure Bash:

date="2009-12-03 15:35:11"
saveIFS="$IFS"
IFS="- :"
date=($date)
IFS="$saveIFS"
for field in "${date[@]}"
do
    echo $field
done

2009
12
03
15
35
11
3

Eine andere Lösung für das OP-Problem:

IFS=' -:' read y m d h m s<<<'2014-03-26 16:36:41'

Konvertierung eines Datums in ein anderes Format mit BSD date und GNU date:

$ LC_ALL=C date -jf '%a %b %e %H:%M:%S %Z %Y' 'Wed Mar 26 16:36:41 EET 2014' +%F\ %T
2014-03-26 16:36:41
$ gdate -d 'Wed Mar 26 16:36:41 EET 2014' +%F\ %T
2014-03-26 16:36:41

GNU date erkennt Wed und Mar auch in nicht-englischen Sprachumgebungen, BSD date jedoch nicht.

Sekunden seit Epoche in Datum und Uhrzeit mit GNU Datum und BSD-Datum umrechnen:

$ gdate -d @1234567890 '+%F %T'
2009-02-14 01:31:30
$ date -r 1234567890 '+%F %T'
2009-02-14 01:31:30

Sekunden in Stunden, Minuten und Sekunden mit einer POSIX-Shell, POSIX awk, GNU date und BSD date umrechnen:

$ s=12345;printf '%02d:%02d:%02d\n' $((s/3600)) $((s%3600/60)) $((s%60))
05:25:45
$ echo 12345|awk '{printf "%02d:%02d:%02d\n",$0/3600,$0%3600/60,$0%60}'
05:25:45
$ gdate -d @12345 +%T
05:25:45
$ date -r 12345 +%T
05:25:45

Sekunden in Tage, Stunden, Minuten und Sekunden umrechnen:

$ t=12345678
$ printf '%d:%02d:%02d:%02d\n' $((t/86400)) $((t/3600%24)) $((t/60%60)) $((t%60))
142:21:21:18
2
Lri

eine weitere pure bash

$ d="2009-12-03 15:35:11"
$ d=${d//[- :]/|}
$ IFS="|"
$ set -- $d
$ echo $1
2009
$ echo $2
12
$ echo [email protected]
2009 12 03 15 35 11
1
ghostdog74

haben Sie versucht, mit cut zu arbeiten? Etwas wie folgt: dayofweek = date|cut -d" " -f1

0
Jay