Дата разбора в Баш - PullRequest
       9

Дата разбора в Баш

52 голосов
/ 03 декабря 2009

Как бы вы проанализировали дату в bash с отдельными полями (годы, месяцы, дни, часы, минуты, секунды) в разные переменные?

Формат даты: YYYY-MM-DD hh:mm:ss

Ответы [ 10 ]

63 голосов
/ 03 декабря 2009

Должен ли это быть Bash? Вы можете использовать GNU coreutils /bin/date для многих преобразований:

 $ 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

Это анализирует данную дату и отображает ее в выбранном формате. Вы можете адаптировать это по своему желанию.

28 голосов
/ 06 декабря 2009

Это просто, просто преобразуйте ваши тире и двоеточия в пробел (не нужно менять IFS) и используйте «read» все в одной строке:

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

Например:

$ 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
16 голосов
/ 12 мая 2017

У меня был другой формат ввода времени, так что вот более гибкое решение.

Конвертировать даты в BSD / macOS

date -jf in_format [+out_format] in_date

, где форматы используют strftime (см. man strftime).

Для заданного формата ввода 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

Чтобы прочитать их в отдельных переменных, я беру идею NVRAM, но позволяю вам использовать любой формат strftime:

$ 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

В сценариях всегда использовать read -r.

В моем случае я хотел преобразовать часовые пояса (имена зон указаны в каталоге /usr/share/zoneinfo):

$ 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

Конвертировать даты в GNU / Linux

На Mac вы можете установить версию GNU date как gdate с brew install coreutils.

date [+out_format] -d in_date

, где out_format использует strftime (см. man strftime).

В команде GNU coreutils date нет способа явно установить формат ввода, так как он пытается выяснить формат ввода сам, и все обычно просто работает. (Подробно вы можете прочитать в руководстве по coreutils: форматы ввода даты .)

Например:

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

Чтобы прочитать их в отдельные переменные, измените команду в разделе Mac, заменив команду в скобках на версию GNU.

Для преобразования между часовыми поясами (см. Каталог /usr/share/zoneinfo для имен зон), вы можете указать TZ="America/Los_Angeles" прямо во входной строке. Обратите внимание на буквенный символ " вокруг имени зоны и символ пробела перед in_date:

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

Например:

$ 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 также понимает смещения часов для часового пояса:

$ TZ=UTC date +"$format" -d '2017-05-09 19:40:01-0700'
2017-05-10 02:40:01+0000
7 голосов
/ 03 декабря 2009
$ 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
5 голосов
/ 06 декабря 2009

Метод массива, возможно, лучше, но это то, что вы специально просили:

IFS=" :-"
read year month day hour minute second < <(echo "YYYY-MM-DD hh:mm:ss")
3 голосов
/ 04 декабря 2009

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
2 голосов
/ 26 марта 2014

Другое решение проблемы ОП:

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

Преобразование даты в другой формат с BSD date и 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 распознает Wed и Mar даже в неанглийских локалях, а BSD date - нет.

Преобразование секунд с начала эпохи в дату и время с датой GNU и датой BSD:

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

Преобразование секунд в часы, минуты и секунды с помощью оболочки POSIX, POSIX awk, GNU date и 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

Преобразование секунд в дни, часы, минуты и секунды:

$ t=12345678
$ printf '%d:%02d:%02d:%02d\n' $((t/86400)) $((t/3600%24)) $((t/60%60)) $((t%60))
142:21:21:18
2 голосов
/ 06 декабря 2009

вместо использования сценариев оболочки включайте в свои сценарии, как показано ниже, где вам нужно:

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

год будет б будет секунд с будет часами. и т. д.

1 голос
/ 04 декабря 2009

еще один чистый удар

$ 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
0 голосов
/ 03 декабря 2009

вы пробовали использовать вырезать? что-то вроде этого: = * День недели 1001 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...