LINUX.ORG.RU

Сортировка даты в файле

 ,


0

1

Здравствуйте! Помогите, пожалуйста, со скриптом. Есть следующая задача.
Дан файл с датами «dd.mm.yyyy 24h:mi:ss» - колонка дат. Найти минимальную, максимальную даты и разницу между ними в секундах. Можно считать, что все даты не менее 01.12.2006 00:00:00. Написал shell-скрипт для сортировки:

#!/bin/sh 
#заменяем точки и двоеточия на пробелы 
sed 's/[:.]/ /g' 5.txt>55.txt 
#сортируем по полям 
sort -k 1.1,1.2n -k 2.1,2.2n -k 3.1,3.4n -k 4.1,4.2n -k 5.1,5.2n -k 6.1,6.2n 55.txt>555.txt 

Однако он правильно сортирует только дату, а время неверно. Подскажите, пожалуйста, как правильно отсортировать время. Кусок файла с датами:

  • 09.12.2006 17:50:08
  • 06.12.2006 14:07:16
  • 06.12.2006 22:33:22
  • 08.12.2006 16:05:47
  • 06.12.2006 12:21:12
  • 08.12.2006 6:15:22
  • 07.12.2006 4:07:12
  • 09.12.2006 2:14:10
  • 06.12.2006 11:28:09
  • 09.12.2006 16:29:40
  • 06.12.2006 22:31:00
  • 06.12.2006 12:00:31
  • 08.12.2006 16:29:51

Откройте форму добавления сообщения в тему и почитайте то, что написано в нижней части формы после слова «Внимание:».

Неужели так сложно просмотреть что ты видишь, прочитать и выполнить?

Вашу «кашу» никто читать не будет, оформите шапку темы правильно.

sort и так отсортирует так, как надо, без дополнительных параметров '-k ...', к тому же хорошо бы, если бы год стоял первым, потом был месяц и в конце день, а потом уже время.

$ cat tst && echo '=====================' && sort tst 
03.01.2015 13:10:09
03.01.2015 12:05:10
02.01.2015 01:01:10
02.01.2014 01:01:10
=====================
02.01.2014 01:01:10
02.01.2015 01:01:10
03.01.2015 12:05:10
03.01.2015 13:10:09

ну а далее просто срезайте посредством tail и head первую и последнюю строку и обрабатывайте их.

Но всё же оформляйте тему правильно в соответствие с разметкой форума, как её узнать я вам уже указал.

Удачи.

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 2)
Ответ на: комментарий от kostik87

Проблема в том, что команда sort сортирует только дату, но не время.
Как правильно отсортировать еще и по времени?

dszn ()
Ответ на: комментарий от dszn

Текстовый файл со строками, на каждой строке отдельная запись.

kostik87 ★★★★★ ()
Ответ на: комментарий от kostik87

По секундам лучше, тс хотел ведь ещё разницу считать. Если время в сек, то просто вычитание. Ну и таймзона может мешать.

emulek ()
$ php -r '$d = explode("\n", trim(file_get_contents("php://stdin"))); usort($d, function($s1, $s2) { return strtotime($s1) - strtotime($s2);}); echo "min=".($min=$d[0])."\nmax=".($max=$d[count($d)-1])."\ndiff=".(strtotime($max)-strtotime($min))."sec\n";' < data.txt
min=06.12.2006 11:28:09
max=09.12.2006 17:50:08
diff=282119sec
KRoN73 ★★★★★ ()
Ответ на: комментарий от emulek

Строго говоря сортировать файл можно так, как есть, затем срезать первую и последнюю строку вывода, а там уже работать с этими двумя строками. Хоть преобразовать в секунды, посчитать разницу и затем обратно преобразовать в дни, часы и минуты.

kostik87 ★★★★★ ()
Ответ на: комментарий от dszn

А где вы видите, что строка «10.12.2006 10:56» подпадает под фомат dd.mm.yyyy 24h:mi:ss, все строки должны быть одного формата, а у вас в этих строках нет секунд. Кроме всего прочего, вместо 9:44 должно быть написано 09:44 и далее секунды. Пока строки не будут одного формата сортировка работать не будет.

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 2)
Ответ на: комментарий от kostik87

Уточняю. Все строки одинакового формата с секундами.
После сортировки по вашему примеру дата и время 10.12.2006 10:56:08 выше, чем 10.12.2006 9:44:44.
Дата 10.12.2006 9:44:44 самая последняя после сортировки, т.е. получается самая максимальная.

dszn ()
Ответ на: комментарий от dszn

Значит преобразуйте строку вместо 10.12.2006 10:56:08 в начале должен быть год. И опять же вместо «10.12.2006 9:44:44» должно быть «10.12.2006 09:44:44».

Если все строки от одного года, то год можно не перемещать вперёд.

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от dszn

Все строки одинакового формата

гений, посмотри внимательно на формат отображения часов.
PS:

echo -e "9\n10"|sort && echo -e "09\n10"|sort
10
9
09
10
теперь альтернативно умным понятнее стало?

novitchok ★★★★★ ()
Ответ на: комментарий от kostik87
#!/bin/sh
sed 's/[:.]/ /g' 5.txt > 55.txt
awk '{print $3"."$2"."$1" "$4":"$5":"$6}' | sort 55.txt > 555.txt 

Результат все равно неверный, опять проблема с сортировкой времени.

dszn ()
Ответ на: комментарий от novitchok

Извиняюсь, конечно 10.12.2006 9:44:44 отображается как 10.12.2006 09:44:44.
Просто ноль не дописал.

dszn ()
Ответ на: комментарий от dszn

Ауу, вы читать умеете? Если вы пишете, что формат строк у вас одинаковый и представляет собой: «dd.mm.yyyy 24h:mi:ss», т.е. 2 символа под день, 2 символа под месяц, 4 символа под год, затем 2 символа под час в 24-х часовом формате, затем 2 символа под минуты, 2 символа под секунды, то строки

08.12.2006 6:15:22
07.12.2006 4:07:12
09.12.2006 2:14:10
не подходят под формат. Ферштейн? Приводите строки к общему формату, что бы в данном случае строки были вот такие:
08.12.2006 06:15:22
07.12.2006 04:07:12
09.12.2006 02:14:10
Потому, что первоначально при сортировке sort сравнивает строки по длине.

Пока у вас данные не будут соответствовать единому формату ничего работать не будет.

kostik87 ★★★★★ ()
Ответ на: комментарий от kostik87

Спасибо за подсказку. Действительно время в разном формате.
Подскажите как привести время к единому формату - по 2 символа на часы, минуты, секунды.

dszn ()
Ответ на: комментарий от dszn
#!/bin/sh

cat $1 | while read LINE
  do
    DATE=`echo $LINE | cut -f1 -d" "`
    TIME=`echo $LINE | cut -f2 -d" "`
    TIME_LEN=${#TIME}
    test $TIME_LEN -lt 8 && echo "${DATE} 0${TIME}" || echo "${DATE} ${TIME}"
  done | tee  ${1}_optimized

Скрипт сохраните в текстовый файл в той же директории, где находится исходный файл, сделайте его исполняемым:

chmod +x script.sh

Запускать вот так:

./script.sh file
на выходе будет создан файл с именем, в данном случае file_optimized.

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от sdio

Отформатировать получилось, нашел максимальную и минимальную даты.
Теперь разбираюсь как посчитать между ними разницу в секундах.
Если я чего-то не понимаю, то спрашиваю, оскорблять-то зачем?

dszn ()
Ответ на: комментарий от zolden

Подскажите как минимальную и максимальную даты, полученные в результате сортировки, перевести в секунды?
Я делаю вот так для минимальной, но не работает

datesec1=$(head -n 1 555.txt)'+%s' 
В файле 555.txt на первой строке - минимальная дата, на последней - максимальная.

dszn ()
Ответ на: комментарий от sdio

Посмотри мои сообщения выше, либо у ТС везде один и тот же год, либо год нужно указывать первым параметром в части строки описывающей дату.

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от dszn

Вот преобразование даты в секунды с отсчётом начала секунд от 1970 года:

date -d "2015-01-07 16:10:37" +%s
1420636237
как видите вашу строку нужно преобразовать, что бы дата была в формате YYY-MM-DD HH:MM:SS.

kostik87 ★★★★★ ()

Вариант без сортировки файла

#!/bin/bash
read LINE
MAXDATE=$(date -d "`echo $LINE |sed 's/\./ /g'|awk '{print $3\"-\"$2\"-\"$1\" \"$4}'`" +%s)
MINDATE=$MAXDATE
MAXDATESTR=$LINE
MINDATESTR=$LINE
while read LINE
do
    DATE1=$(date -d "`echo $LINE |sed 's/\./ /g'|awk '{print $3\"-\"$2\"-\"$1\" \"$4}'`" +%s)
    if  [ $DATE1 -gt $MAXDATE ]
    then
        MAXDATE=$DATE1
        MAXDATESTR=$LINE
    elif [ $DATE1 -lt $MINDATE ]
    then
        MINDATE=$DATE1
        MINDATESTR=$LINE
    fi
done
echo $MINDATESTR
echo $MAXDATESTR
echo `expr $MAXDATE - $MINDATE`

gorky ★★ ()
Ответ на: комментарий от kostik87

date -d «2015-01-07 16:10:37» +%s

$ date -d '07/01/2015 16:10:37' +%s
1435756237

как видите в вашей строке достаточно заменить точки в дате на слеши и всё, можно преобразовывать в секунды

sdio ★★★★★ ()
Ответ на: комментарий от kostik87

Строго говоря сортировать файл можно так, как есть

Строго говоря ... бла-бла-бла

Нельзя ведь, зачем так настаивать на глупостях?

sdio ★★★★★ ()
Ответ на: комментарий от sdio

Каким образом в выражении date -d '07/01/2015 16:10:37' +%s вместо «07/01/2015 16:10:37» подставить найденное значение
максимальной и минимальной дат, которые я нашел?

dszn ()
Ответ на: комментарий от sdio

$FOUNDVALUE - это переменная, в которой хранится нужное значение даты, насколько я понимаю?
А принципиально какой формат даты?

dszn ()
Ответ на: комментарий от dszn

Да

Не принципиально, главное чтобы date ее понял.

sdio ★★★★★ ()
Ответ на: комментарий от dszn
datestr1=`head -n 1 555.txt | sed 's/\./ /g' | awk '{print $3 "-" $2 "-" $1 " " $4}'`
datesec1=`date -d "$datestr1" +%s`

Лучше использовать формат даты «2015-01-07 16:10:37». Предложенный sdio формат даты «07/01/2015 16:10:37» читается по американским правилам, по которым сначала указывается месяц, а потом день месяца.

date -d "07/01/2015 16:10:37" +%c
Ср. 01 июля 2015 16:10:37

gorky ★★ ()
Ответ на: комментарий от gorky

Спасибо, получилось перевести максимальную и минимальную даты в секунды .
Теперь считаю разницу между ними в секундах

datestr1=`head -n 1 555.txt | sed 's/\./ /g' | awk '{print $3 "-" $2 "-" $1 " " $4}'`;
datesec1=`date -d "$datestr1" +%s`;
datestr2=`tail -n 1 555.txt | sed 's/\./ /g' | awk '{print $3 "-" $2 "-" $1 " " $4}'`;
datesec2=`date -d "$datestr2" +%s`;
expr $datesec2-$datesec1 $diff;
echo $diff;
Но на экран выводится не разница, а само выражение: expr 1165761038-1165351073. Как исправить скрипт, чтобы работало?

dszn ()
Ответ на: комментарий от dszn

Получилось, надо было вот так:

echo `expr $datesec2 - $datesec1`;
Спасибо всем, кто помогал и подсказывал!

dszn ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.