2009-12-03 14 views
39

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

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

Antwort

52

Hat es bash sein? Sie können die GNU coreutils /bin/date Binary 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 

Dieser analysiert das angegebene Datum und zeigt sie im gewählten Format. Sie können dies nach Belieben Ihren Bedürfnissen anpassen.

+6

Ist das eine Linux-Erweiterung? Weder FreeBSD noch Mac OSX scheinen das zu unterstützen. –

+1

Es ist das gute alte GNU Datum: $ date --Version Datum (GNU coreutils) 7.4 Copyright (C) 2009 Free Software Foundation, Inc. Lizenz GPLv3 +: GNU GPL Version 3 oder höher . Dies ist freie Software: Sie können sie ändern und neu verteilen. Es gibt KEINE GEWÄHRLEISTUNG, soweit gesetzlich zulässig. Geschrieben von David MacKenzie. –

+0

Warum funktioniert 'date --date =" \ 'date \' "' nicht? – Luc

6
$ 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 
+2

keine Notwendigkeit, externen Befehl aufzurufen – ghostdog74

0

haben Sie versucht mit Schnitt? etwas wie folgt aus: dayofweek = date|cut -d" " -f1

+0

Das trennt nur das Datum und die Zeit, nicht jedes Teil einzeln. –

2

Reines 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 
+0

Keine Notwendigkeit, Arrays hier zu verwenden. Just 'set Junk $ Datum; shift' anstelle von 'date = ($ date)' und 'for field' anstelle der Array-Schleife. Das wäre eine 'pure sh' Version, die noch besser ist! – Idelic

1

andere reine 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 
3

Das Array-Methode ist vielleicht besser, aber das ist, was Sie speziell für fragten:

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

Ich mag das am besten. Eine Abkürzung, die IFS auch nicht dauerhaft ändert: 'IFS =": - "lese Y M D h m s <<<" JJJJ-MM-TT hh: mm: ss "' – ephemient

25

Dies ist einfach, nur Ihre Bindestriche und Doppelpunkte zu einem Raum (keine Notwendigkeit zu ändern IFS) ‚lesen‘ in einer Zeile und verwenden konvertieren:

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 
2

statt durch Shell Scripting, sich unten in Ihrem Scripting integrieren wie wheever Sie brauchen:

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

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

2

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

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

ein Datum in ein anderes Format mit BSD konvertieren 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 in nicht Wed und Mar selbst erkennt Englisch Locales aber BSD date nicht.

Konvertieren von Sekunden seit Epoche zu einem Datum und Zeit mit GNU Datum und BSD Datum:

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

Konvertieren von Sekunden bis Stunden, Minuten und Sekunden mit einem POSIX-Shell, POSIX awk, GNU date und BSD date :

$ 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 

Konvertieren von Sekunden bis Tagen, Stunden, Minuten und Sekunden:

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

Ich hatte ein anderes Eingabezeitformat, also hier ist eine flexiblere Lösung. Der Befehl zum konvertieren Daten in BSD/macOS ist

date -jf in_format [+out_format] in_date 

wo die Formate strftime (siehe man strftime).

Für das gegebene 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 sich in einzelne Variablen zu lesen, ich bin NVRAM Idee nehmen, aber so dass Sie jedes strftime Format verwenden:

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

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

$ read 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 meinem Fall, ich wollte zwischen Zeitzonen umwandeln (siehe Ihr /usr/share/zoneinfo Verzeichnis für Zonennamen):

$ 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