преобразовать поле столбца текстового файла с данными dd.mm.yy в dd.mm.YYYY

-1

Как отформатировать дату для содержимого файла с помощью инструментов командной строки Linux?

Исходные данные:
aaa; 1.70; ccc; 20.01.13; zz; 2013;
ууу; 2,70; LLL; 17.12.10; ZZ; 2013;
FFF; 3,70; NNN; 31.01.98; ZZ; 2013;
AUU; 8,70; нуу; 30.02.96; ZZ; 2013;

Выход:
AAA; 1,70; CCC; 20.01.2013; ZZ; 2013;
ууу; 2,70; LLL; 17.12.2010; ZZ; 2013;
FFF; 3,70; NNN; 31; 01.1998; ZZ; 2013;
AUU; 8,70; нуу; 30.02.1996; ZZ; 2013;

Maris
источник

Ответы:

0

Предполагая, что любой двузначный год между 70 и 99 происходит в прошлом веке:

sed 's/[7-9][0-9];$/19&/; s/[0-6][0-9];$/20&/' file

Или пусть кто-то другой решит:

perl -MTime::Piece -F';' -ane '
    $F[-2] = Time::Piece->strptime($F[-2], "%d.%m.%y")->strftime("%d.%m.%Y");
    print join(";", @F)
' file

Параметры

  • -MTime::Pieceимпортирует стандартный модуль Perl Time :: Piece
  • -F';' -aпараметры разделяют каждую строку точкой с запятой и сохраняют результат в @Fмассиве
  • -n зацикливается на строках входных данных (стандартный или файл) без автоматической печати каждой строки.

Код

  • $F[-2]является вторым последним полем (где дата была в вашем исходном вопросе).
  • Я использую strptimeи strftimeметоды для анализа и форматирования даты.

Итак, если у вас есть даты, которые должны быть изменены в столбцах с 12 по 15, используйте

perl -MTime::Piece -F';' -ane '
    sub reformat {
        return Time::Piece->strptime(shift, "%d.%m.%y")->strftime("%d.%m.%Y");
    }
    for my $i (11..14) {
        $F[$i] = reformat $F[$i];
    }
    print join(";", @F)
' file
Гленн Джекман
источник
Вы можете прокомментировать, как это работает? Это хорошо с примером, но когда я ставлю более длинную строку с несколькими датами, это как-то дает 01.01.1970 в конце строки. Хотелось бы, чтобы это изменило формат даты для столбца с номером 12. а после столбца 12 есть другие 10 столбцов. Даты должны быть изменены в столбцах 12 и 15. Другие поля / столбцы не должны быть изменены.
Марис
Работает как шарм! Только я отделился для своего $ i (11) и второй раз, когда я взял свой $ i (14), не работал вместе 11..14, Время разбора ошибки в /usr/lib/perl/5.14/Time/Piece.pm строка 469, <> строка 1. :)
Марис
0

Это можно сделать с помощью awk:

   awk -F'[;.]' '{if ($6 <= 13) x=20$6; else x = 19$6 ; print \
                  $1";"$2";"$3";"$4"."$5"."x";"}' 

Эта команда разделяет поля с разделителями ;и .. Затем он изменяет последнее поле следующим образом: если оно меньше или равно 13, оно преобразуется в 20last_field, в противном случае оно преобразуется в 19last_filed, а затем печатает поля в том же порядке, что и раньше, с теми же разделителями, включая модифицированное шестое поле (теперь называется x).

MariusMatutiae
источник
Это также может быть хорошим решением, но проблема в том, что поля не могут быть разделены с помощью "." потому что иногда может быть некоторая информация с точкой до $ 6, и тогда она будет засчитана неправильно.
Марис
@Maris Вы должны были заявить об этом в ОП.
MariusMatutiae
0

Использование dconvиз dateutils :

dconv -Si '%d.%m.%y' -f '%d.%m.%Y' <<EOF
aaa;1.70;ccc;20.01.13;zz;2013;
uuu;2.70;lll;17.12.10;zz;2013;
fff;3.70;nnn;31.01.98;zz;2013;
auu;8.70;nuu;30.02.96;zz;2013;
EOF

производит именно тот результат, который вы хотите.

hroptatyr
источник