Как преобразовать формат даты в файле

Как преобразовать формат даты в файле

Входной файл:Содержит 3 столбца, третий столбец — дата в DD-MMM-YYYYформате
выборочных данных:

1232,abdc, 02-Jan-2014
4534,kdafh, 20-Feb-2014
364,asjhdk, 11-Jul-2012

требуемый вывод:

1232,abdc, 2014-01-02
4534,kdafh, 2014-02-20
364,asjhdk, 2012-07-11

использование функции date: date -d 20-DEC-2014 +%Y-%m-%d
при ее использовании команда awk выдает ошибку
Есть ли другой способ?

решение1

Один из возможных ответов с использованием awk, предполагая, что входной файл — input-file.txt, а выходной файл — output-file.txt:

awk -F ',' '{printf("%s,%s,",$1,$2);system("date -d "$3" +%Y-%m-%d");}' input-file.txt > output-file.txt

решение2

С использованиемМиллер( mlr) для очистки избыточного пробела в заголовочном CSV-входе и затем перезаписи 3-го поля. 3-е поле переписывается путем разбора заданной даты с использованием strptime()строки формата времени %d-%b-%Yи последующего переформатирования полученной временной метки Unix с использованием strftime()и %Fстроки форматирования (можно использовать, например, %Y-%m-%dвместо %F):

mlr --csv -N \
    clean-whitespace then \
    put '$3 = strftime(strptime($3,"%d-%b-%Y"),"%F")' file

Учитывая данные в вопросе, это выведет

1232,abdc,2014-01-02
4534,kdafh,2014-02-20
364,asjhdk,2012-07-11

Если ваши данные имеют временную метку в том же поле, вы можете настроить строки формата, используемые в вызовах strptime()и strftime(), в соответствии со своими потребностями.

Ознакомьтесь с руководством strftimeпо вашей системе, чтобы узнать, что означают эти строки форматирования и какие существуют варианты форматирования даты и времени.

решение3

Предположим, что вы вводите такой текст:

1232,abdc, 02-Jan-2014 18:01:37</br> 
4534,kdafh, 20-Feb-2014 07:17:19</br>
364,asjhdk, 11-Jul-2012 23:20:30</br>

Мой ответ был бы таким:

cat input-file.txt | sed 's[</br>[[g' | awk -F ',' '{printf("%s,%s,",$1,$2);system("date -d \""$3" "$4"\" +\"%Y-%m-%d %H:%M:%S\"");}' > output-file.txt

А если записи находятся на одной строке (во входном файле нет новой строки после </br>, то это будет

cat input-file.txt | sed 's[</br>[\n[g' | awk -F ',' '{printf("%s,%s,",$1,$2);system("date -d \""$3" "$4"\" +\"%Y-%m-%d %H:%M:%S\"");}' > output-file.txt

решение4

Вы не хотите создавать новый процесс, который выполняет оболочку и другую команду для каждой строки файла, это было бы очень неэффективно. Наличие интерпретирующего кода оболочки на основе ввода также является рецептом для внедрения уязвимостей инъекции команд. Более того, этот -dвариант нестандартен.

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

perl -MTime::Piece -pe '
  s{\d+-\w+-\d+$}{Time::Piece->strptime($&, "%d-%b-%Y")->ymd}e
  ' < your-file

Там мы сопоставляем <digits>-<word-characters>-<digits>найденное в конце строки ( $), интерпретируем его как <day>-<month-abbrev>-<year>и переформатируем как, <yead>-<month>-<day>используя основной модуль Perl Time::Piece.

Связанный контент