сортировать по хронологическому порядку работы

сортировать по хронологическому порядку работы

Возможно, простое решение, которое я потерял. Как мне отсортировать вывод в atqхронологическом порядке, чтобы я мог легко увидеть, кто должен баллотироваться следующим? Страница manдля sortне имеет ничего встроенного для распознавания временных меток, подобных следующим:

atq
1264    Sat Mar 24 15:03:00 2012 a master
1445    Sat Mar 24 20:28:00 2012 a master
1548    Sun Mar 25 15:09:00 2012 a master
1193    Sat Mar 24 11:03:00 2012 a master
1359    Sat Mar 24 17:13:00 2012 a master
1726    Mon Mar 26 21:24:00 2012 a master
1736    Mon Mar 26 22:04:00 2012 a master
1748    Mon Mar 26 22:46:00 2012 a master
1704    Mon Mar 26 20:19:00 2012 a master
1288    Sat Mar 24 15:38:00 2012 a master
1532    Sun Mar 25 11:53:00 2012 a master

atq |sortне будет работать ни при каком переключении идентификатора задания.

решение1

Если вы работаете в Linux, вывод atqвсегда имеет дату в одном и том же формате. Отсортируйте поля в соответствующем порядке, обращая внимание на то, какие из них являются числами или названиями месяцев. Обязательно используйте английскую локаль для названий месяцев, так как именно она atqиспользуется.

atq | sort -k 6n -k 3M -k 4n -k 5 -k 7 -k 1
#          year  month day   time queue id

решение2

Команда sortможет это сделать, но, к сожалению, вы не можете использовать --month-sortи --numeric-sortвместе. Поэтому используйте:

$ atq |
    sed 's/Jan/1/;s/Feb/2/;s/Mar/3/;s/Apr/4/;s/May/5/;s/Jun/6/;s/Jul/7/;s/Aug/8/;s/Sep/9/;s/Oct/10/;s/Nov/11/;s/Dec/12/' |
    sort -n -k6,6 -k3,4

Это преобразует сокращения месяцев в их числовые значения, затем сортирует сначала по году ( -k6,6), затем по месяцу и дню ( -k3,4). В выводе не будет названий месяцев, но если вы действительно хотите, вы можете преобразовать их обратно с помощью другого sed.

$ atq |
    sed 's/Jan/1/;s/Feb/2/;s/Mar/3/;s/Apr/4/;s/May/5/;s/Jun/6/;s/Jul/7/;s/Aug/8/;s/Sep/9/;s/Oct/10/;s/Nov/11/;s/Dec/12/' |
    sort -n -k6,6 -k3,4 |
    sed 'h;s/^[0-9][0-9]*  *[A-Z][a-z][a-z] *\([0-9][0-9]*\).*/\1/;s/10/Oct/;s/11/Nov/;s/12/Dec/;s/1/Jan/;s/2/Feb/;s/3/Mar/;s/4/Apr/;s/5/May/;s/6/Jun/;s/7/Jul/;s/8/Aug/;s/9/Sep/;G;s/^\(.*\)\n\([0-9][0-9]*  *[A-Z][a-z][a-z] *\)[0-9][0-9]*\( .*\)/\2\1\3/'

Обратите внимание, что это s/12/Dec/должно стоять перед s/1/Jan/.

решение3

Выглядит сложно, но это тоже работает:

atq |awk '{system("echo "$1 "  $(date +%Y-%m-%d_%H-%M-%S \
--date \""$2" "$3" "$4" "$5" "$6"\")  "$7"  "$8 )}' |sort -k2 
    469  2012-03-24_01-30-00  a  master
    655  2012-03-24_02-03-00  a  master
    671  2012-03-24_02-04-00  a  master
    657  2012-03-24_02-09-00  a  master
    673  2012-03-24_02-11-00  a  master
    537  2012-03-25_00-38-00  a  master
    539  2012-03-25_00-43-00  a  master
    652  2012-03-27_12-57-00  a  master
    654  2012-03-27_13-03-00  a  master
    656  2012-03-27_13-09-00  a  master

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

Вы можете добавить |column -t в конце значок , чтобы аккуратно выровнять и разнести поля.

решение4

atqпозволяет определить »формат времени типа strftime«. Можно использовать эпоху для легкой сортировки и позже преобразовать ее во что-то читаемое. Эпоха также имеет то преимущество, что можно выполнять расчеты времени.

$ atq -o%s | sort -k2n | while read -r id epoch data; do
    echo "$id $(date --date @$epoch) $data"
done

Я использую этот метод в скрипте, atqqкоторый

  • сортирует задания по дате,
  • распечатывает команду задания и
  • показывает продолжительность времени до наступления события.

Пример вывода:

$ atqq
5515 2023-11-02 12:00:00 a user: "strobe blue" (1:59:08)
5514 2023-11-02 12:30:00 a user: "strobe red" (2:29:08)
#!/bin/bash

duration() {
        local i=$1
        local d=$((i / (3600 * 24)))
        ((i %= 3600 * 24))
        local h=$((i / 3600))
        ((i %= 3600))
        local m=$((i / 60))
        local s=$((i % 60))

        if [ $d -gt 0 ]; then
                printf "%ud %u:%02u:%02u" $d $h $m $s
        elif [ $h -gt 0 ]; then
                printf "%u:%02u:%02u" $h $m $s
        elif [ $m -gt 0 ]; then
                printf "%u:%02u" $m $s
        else
                printf "%u" $s
        fi
}

now=$(date +%s)

atq -o%s | sort -k2n | while read -r id epoch data; do
        date=$(date --date @$epoch +%F\ %T)
        cmd=$(at -c $id | sed '/^$/d' | tail -1)
        diff=$((epoch - now))
        if [ $diff -gt 0 ]; then
                remaining="\e[32m$(duration $diff)\e[m"
        else
                remaining="\e[31m-$(duration ${diff#-})\e[m"
        fi

        echo -e "\e[1m$id\e[m $date $data: \e[33m\"$cmd\"\e[m ($remaining)"
done

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