Hoe zou je een datum in bash, met afzonderlijke velden (jaren, maanden, dagen, uren, minuten, seconden) in verschillende variabelen ontleden?
Het datumformaat is: YYYY-MM-DD hh:mm:ss
Antwoord 1, autoriteit 100%
Moet het bash zijn? U kunt het binaire bestand GNU coreutils /bin/date
gebruiken voor veel transformaties:
$ 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
Hiermee wordt de opgegeven datum geparseerd en weergegeven in het gekozen formaat. U kunt dat naar believen aanpassen aan uw behoeften.
Antwoord 2, autoriteit 39%
Dit is eenvoudig, converteer gewoon uw streepjes en dubbele punten naar een spatie (u hoeft IFS niet te wijzigen) en gebruik ‘lees’ alles op één regel:
read Y M D h m s <<< ${date//[-:]/ }
Bijvoorbeeld:
$ 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
Antwoord 3, autoriteit 32%
Ik had een ander invoertijdformaat, dus hier is een flexibelere oplossing.
Datums converteren in BSD/macOS
date -jf in_format [+out_format] in_date
waar de indelingen strftime gebruiken (zie man strftime
).
Voor het opgegeven invoerformaat 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
Om ze in afzonderlijke variabelen te lezen, neem ik het idee van NVRAM over, maar laat je elk strftime-formaat gebruiken:
$ 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 mijn geval wilde ik converteren tussen tijdzones (zie uw /usr/share/zoneinfo
directory voor zonenamen):
$ 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
Datums converteren in GNU/Linux
Op een Mac kun je de GNU-versie van
date
installeren alsgdate
metbrew install coreutils
.
date [+out_format] -d in_date
waar het out_format strftime gebruikt (zie man strftime
).
In het date
-commando van GNU coreutils is er geen manier om expliciet een invoerformaat in te stellen, aangezien het het invoerformaat zelf probeert te achterhalen, en dingen werken meestal gewoon. (Voor details kunt u de handleiding lezen op coreutils: Invoerformaten voor datum.)
Bijvoorbeeld:
$ date '+%Y %m %d %H %M %S' -d '2017-05-10 13:40:01'
2017 05 10 13 40 01
Om ze in afzonderlijke variabelen te lezen:
$ read -r y m d H M S <<< "$(date '+%Y %m %d %H %M %S' -d "$date_in")"
Om tussen tijdzones te converteren (zie uw /usr/share/zoneinfo
directory voor zonenamen), kunt u TZ="America/Los_Angeles"
direct in uw invoer specificeren snaar. Let op de letterlijke tekens "
rond de zonenaam en het spatieteken vóór in_date:
TZ=out_tz date [+out_format] 'TZ="in_tz" in_date'
Bijvoorbeeld:
$ 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-datum begrijpt ook uurverschuivingen voor de tijdzone:
$ TZ=UTC date +"$format" -d '2017-05-09 19:40:01-0700'
2017-05-10 02:40:01+0000
Antwoord 4, autoriteit 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
Antwoord 5, autoriteit 7%
De array-methode is misschien beter, maar dit is waar je specifiek om vroeg:
IFS=" :-"
read year month day hour minute second < <(echo "YYYY-MM-DD hh:mm:ss")
Antwoord 6, autoriteit 3%
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
Antwoord 7, autoriteit 2%
in plaats van de shell-scripting te gebruiken, neem je in je scripting zelf op zoals hieronder wat je maar wilt:
a=date +%Y
b=date +%S
c=date +%H
een jaar wordt
b zal seconden zijn
c zal uren zijn. enzovoort.
Antwoord 8, autoriteit 2%
Een andere oplossing voor het probleem van de OP:
IFS=' -:' read y m d h m s<<<'2014-03-26 16:36:41'
Een datum converteren naar een ander formaat met BSD date
en 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
herkent Wed
en Mar
zelfs in niet-Engelse talen, maar BSD date
niet.
Seconden sinds epoche converteren naar een datum en tijd met GNU-datum en BSD-datum:
$ gdate -d @1234567890 '+%F %T'
2009-02-14 01:31:30
$ date -r 1234567890 '+%F %T'
2009-02-14 01:31:30
Seconden omrekenen naar uren, minuten en seconden met een POSIX-shell, POSIX awk
, GNU date
en 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
Seconden omzetten in dagen, uren, minuten en seconden:
$ t=12345678
$ printf '%d:%02d:%02d:%02d\n' $((t/86400)) $((t/3600%24)) $((t/60%60)) $((t%60))
142:21:21:18
Antwoord 9
nog een pure bash
$ d="2009-12-03 15:35:11"
$ d=${d//[- :]/|}
$ IFS="|"
$ set -- $d
$ echo $1
2009
$ echo $2
12
$ echo $@
2009 12 03 15 35 11
Antwoord 10
Heb je al geprobeerd om knippen te gebruiken?
iets zoals dit:
dayofweek=date|cut -d" " -f1