Преобразование дат в оболочке - PullRequest
2 голосов
/ 22 декабря 2011

Как я могу преобразовать один формат даты в другой формат в шеллскрипте?

Пример:

старый формат

MM-DD-YY HH:MM

но я хочу преобразовать его в

YYYYMMDD.HHMM

Ответы [ 4 ]

2 голосов
/ 22 декабря 2011

Воспользуйтесь преимуществами разделения слов оболочки и позиционных параметров:

date="12-31-11 23:59"
IFS=" -:"
set -- $date
echo "20$3$1$2.$4$5"  #=> 20111231.2359
2 голосов
/ 22 декабря 2011

Как "20${D:6:2}${D:0:2}${D:3:2}.${D:9:2}${D:12:2}00", если старая дата в переменной $D.

0 голосов
/ 22 декабря 2011
 myDate="21-12-11 23:59"
 #fmt is DD-MM-YY HH:MM
 outDate="20${myDate:6:2}${myDate:3:2}${myDate:0:2}.${myDate:9:2}${myDate:12:2}00"

 case "${outDate}" in 
    2[0-9][0-9][0-9][0-1][0-9][0-3][0-9].[0-2][0-9][0-5][[0-9][0-5][[0-9] ) 
      : nothing_date_in_correct_format 
    ;; 
    * ) echo bad format for ${outDate} >&2
    ;; 
 esac

Обратите внимание, что если у вас есть большой файл для обработки, то вышеприведенный процесс дорогой (ish). Для данных на основе файлов я бы порекомендовал что-то вроде

 cat infile
 ....|....|21-12-11 23:59|22-12-11 00:01| ...|

 awk '
    function reformatDate(inDate) {
       if (inDate !~ /[0-3][0-9]-[0-1][0-9]-[0-9][0-9] [0-2][0-9]:[0-5][[0-9]/) {
         print "bad date format found in inDate= "inDate
         return -1
       }
       # in format assumed to be DD-MM-YY HH:MM(:SS)
       return (2000 + substr(inDate,7,2) ) substr(inDate,4,2) substr(inDate, 1,2) \
              "." substr(inDate,10,2) substr(inDate,13,2) \
               ( substr(inDate,16,2) ?  substr(inDate,16,2) : "00" )
    }
    BEGIN {       
       #add or comment out for each column of data that is a date value to convert
       # below is for example, edit as needed.
       dateCols[3]=3
       dateCols[4]=4
       # for awk people, I call this the pragmatic use of associative arrays ;-)

       #assuming pipe-delimited data for columns
       #....|....|21-12-11 23:59|22-12-11 00:01| ...|
       FS=OFS="|"
    }
    # main loop for each record
    {
       for (i=1; i<=NF; i++) {
         if (i in dateCols) {
            #dbg print "i=" i "\t$i=" $i
            $i=reformatDate($i)
         }
       }
       print $0
    }' infile

выход

.... | .... | +20111221,235900 | +20111222,000100 | ... |

Надеюсь, это поможет.

0 голосов
/ 22 декабря 2011

Хороший ответ уже есть, но вы сказали, что вы хотели найти альтернативу в комментариях, поэтому вот мой [довольно ужасный в сравнении] метод:

read sourcedate < <(echo "12-13-99 23:59");
read sourceyear < <(echo $sourcedate | cut -c 7-8);
if [[ $sourceyear < 50 ]]; then
read fullsourceyear < <(echo -n 20; echo $sourceyear);
else
read fullsourceyear < <(echo -n 19; echo $sourceyear);
fi;
read newsourcedate < <(echo -n $fullsourceyear; echo -n "-"; echo -n $sourcedate | cut -c -5);
read newsourcedate < <(echo -n $newsourcedate; echo -n $sourcedate | cut -c 9-14);
read newsourcedate < <(echo -n $newsourcedate; echo :00);
date --date="$newsourcedate" +%Y%m%d.%H%M%S

Итак, первая строка просто читаетдата, затем мы получаем двузначный год, а затем добавляем его к '20' или '19' на основе, если оно меньше 50 (так что это даст вам годы с 1950 по 2049 год - не стесняйтесь переносить строку).Затем мы добавляем дефис и месяц и дату.Затем мы добавляем пробел и время, и, наконец, мы добавляем ':00' в качестве секунд (снова не стесняйтесь, чтобы сделать свой собственный по умолчанию).Наконец, мы используем дату GNU, чтобы прочитать ее (поскольку она теперь стандартизирована) и распечатать ее в другом формате (который вы можете редактировать).

Это намного длиннее и страшнее, чем разрезание строки, ноформат в последней строке может стоить того.Кроме того, вы можете значительно сократить его с сокращением, которое вы только что узнали в первом ответе.

Удачи.

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