Не хочу заводить похожую тему, поэтому попробую спросить тут.
Как перевести в unixtime дату в виде 20110223122334 (это +%Y%m%d%H%M%S)?
Конечно если руками переформатировать в вид 2011-02-23 12:23:34 работать будет, но есть необходимость в модификации и пересчёте даты в нескольких тысячах строк.
Подозреваю можно через set задать в системе дату в таком формате сначала, но на сервере баловство с установкой даты чревато
Ну, честно говоря, замена даты лишь одна часть проблемы.
Дело в том, что это очень большой файл с разделителями, дата в 11м поле.
Дата неправильная и мне надо её исправлять на правильную (текущее значение + смещение в секундах для поправки)
Для этого и собирался переводить в unixtime, прибавлять смещение, потом переводить обратно).
Я про sed уже тоже думал (и про awk), но ничего толкового не придумал.
Пример записи (дата - 20110221220506):
Мой воспалённый мозг родил такую конструкцию, обходящуюся лишь bash и sed и tr 1. Насколько я понял, файл идёт в одну строку, записи разделены вертикальной чертой. Расположим для удобства каждую запись в отдельной строке, предварительно убрав последнюю вертикальную черту в изначальном файле во избежание пустой строки в конце всех последующих файлов:
$ sed "s/|/\\`echo -e '\n\ '`/g" initial_file | sed -e "s/^\ //g" > every_record_in_separted_line_file
Простите за костыль с пробелом, просто \n не сработало.
2. Делим файл на три части-колонки: до даты, саму дату, после даты
$ sed "s/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*$//g" every_record_in_separted_line_file > first_column_file
$ sed "s/\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*$//g" every_record_in_separted_line_file | sed "s/^[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,//g" > second_column_file
$ sed "s/^[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]//g" every_record_in_separted_line_file > third_column_file
3. Делаем из второй колонки скрипт для преобразования в unix epoch time (можно сразу с корректировкой, но у меня с ходу получилось только добавить +second +minute +hour итп, но несколько, например, +4second, не получилось, добавило зону)
$ sed "s/^[0-9][0-9][0-9][0-9]/&\-/g" second_column_file | sed "s/^[0-9][0-9][0-9][0-9]\-[0-9][0-9]/&\-/g" | sed "s/^[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]/&\ /g" | sed "s/^[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]\ [0-9][0-9]/&\:/g" | sed "s/^[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]\ [0-9][0-9]\:[0-9][0-9]/&\:/g" | sed "s/^/date\ \-\-date\=\'/g" | sed "s/$/\'\ \+\%s/g" > convert_date_script
Не знаю насколько большой у вас файл, если большой, то на пайпах может захлебнуться и придётся разбивать на отдельные операции с выхлопом во временный файл. Конвертируем даты в epoch time
$ sh convert_date_script > second_column_file_in_unix_epoch
4. Выполняем коректировку времени (там добавление секунд что ли)
$ sed "s/^/echo\ \$\(\(/g" second_column_file_in_unix_epoch | sed "s/$/\+87\)\)/g" > date_addition_script
$ sh date_addition_script > second_column_file_added_unix_epoch
6. Преобразовываем в родной формат
$ sed "s/^/date\ \-\-date\=\"\@/g" second_column_file_added_unix_epoch | sed "s/$/\"\ \+\%Y\%m\%d\%H\%M\%S/g" > convert_to_old_format_script
$ sh convert_to_old_format_script > second_column_file_added
Вы мой герой, раз смогли сделать такое - выглядит потрясно.
Но вы меня простите, так как я вас ввёл в заблуждение (совершенно без злого умысла).
Разделители тут всё-таки - запятые.
Всего порядка 74х полей.
Пайп ближе к концу - это законный символ одного из полей.
Плюс, почему я не смог сделать этого седом в лоб - поля могут быть переменной длины и даже пустые.
Объём - сотни мегабайт. Вот трёхстрочный пример.
Может я что-то недопонял, что что мешает взять любой скриптовый язык,
* Отсплитить строку в массив по разделителям.
* Перевести одиннадцатое поле в unixtime, прибавить поправку и перевести обратно.
* Заджойнить массив в строку.
* Повторять до конца файла.
А, ну тогда без первого пункта, раз вертикальная черта-законный символ. \,[^\,]* соответствует запятая и потом блок из нуля и более любых символов кроме самой запятой, это заменяет что ,,, что ,5
Тогда надо регекспы дополнить до нужного количества полей, я думаю вы разберётесь как.
Отсплитить мне ничего не мешает.
Мой первый вопрос как раз и был про нормальный способ перевести время моём текущем формате в unixtime, вы видимо его прокрутили.
Спасибо за наводочку. Уж было порадовался что можно будет переписать на awk, но к удивлению обнаружил там только strftime. Ф-ции strptime там почему-то нет