PS1 подскажите, чтобы показать прошедшее время

10

В настоящее время я использую это для отображения текущего времени в моем приглашении bash:

PS1=\[\e[0;32m\]\t \W>\[\e[1;37m\]

20:42:23 ~>

Можно ли отобразить прошедшее время с предыдущего запроса? Такие как:

00:00:00 ~> sleep 10
00:00:10 ~> sleep 20
00:00:20 ~>

Это не имеет ничего общего с. Можно ли периодически менять PS1 скриптом в фоновом режиме?

TeasingDart
источник
Нет, в этом сообщении нет ответа, и я ожидаю, что приглашение изменится только при отображении нового приглашения.
TeasingDart
Нет, на самом деле нереального способа сделать то, что вы просите, нет.
DopeGhoti
1
Это возможно, если отображаемое значение является статическим (вопрос OP, казалось, не позволял это). Истекшее время можно сохранить, сохранив время эпохи предыдущего времени в переменной оболочки. Реализация этого кажется большой работой (хотя час или около того - возможно, кто-то предоставит более простое решение, чем то, что я имею в виду). Этот вопрос будет полезен.
Томас Дики

Ответы:

10

Один из способов сделать это - использовать функцию bash PROMPT_COMMAND для выполнения кода, модифицирующего PS1. Функция ниже является обновленной версией моего исходного представления; этот использует две переменные окружения меньше и ставит перед ними префикс «_PS1_», чтобы избежать путаницы в существующих переменных.

prompt_command() {
  _PS1_now=$(date +%s)
  PS1=$( printf "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
           $((  ( _PS1_now - _PS1_lastcmd ) / 3600))         \
           $(( (( _PS1_now - _PS1_lastcmd ) % 3600) / 60 )) \
           $((  ( _PS1_now - _PS1_lastcmd ) % 60))           \
       )
  _PS1_lastcmd=$_PS1_now
}
PROMPT_COMMAND='prompt_command'
_PS1_lastcmd=$(date +%s)

Поместите это в свой .bash_profile, чтобы все началось.

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

00:00:02 ~> sleep 5   ## here I typed really quickly
00:00:05 ~> sleep 3   ## here I took about 2 seconds to enter the command
00:00:10 ~> sleep 30 ## more slow typing
00:01:35 ~>

Позднее добавление:

Основываясь на удаленном ответе @Cyrus, вот версия, которая не загромождает среду дополнительными переменными:

PROMPT_COMMAND='
    _prompt(){
        PROMPT_COMMAND="${PROMPT_COMMAND%-*}-$SECONDS))\""
        printf -v PS1 "\[\e[0;32m\]%02d:%02d:%02d \W>\[\e[1;37m\] " \
                      "$(($1/3600))" "$((($1%3600)/60))" "$(($1%60))"
    }; _prompt "$((SECONDS'"-$SECONDS))\""

Дополнительное добавление:

Начиная с bash версии 4.2 ( echo $BASH_VERSION), вы можете избежать внешних dateвызовов с помощью новой строки формата printf; заменить $(date +%s)части с $(printf '%(%s)T' -1). Начиная с версии 4.3 , вы можете опустить -1параметр, чтобы полагаться на поведение «без аргументов значит сейчас ».

Джефф Шаллер
источник
Это очень близко. Это работает, когда я копирую / вставляю из приглашения bash, но когда я пытался добавить его в мой .bashrc, он печатает «1451424431: команда не найдена»
TeasingDart
может быть, слишком много получилось скопировать / вставить?
Джефф Шаллер
Эта последняя версия работала, именно то, что я хотел! Я думаю, что это было связано с моей ловушкой, чтобы установить цвет текста после приглашения. Спасибо.
TeasingDart
при сбросе $SECONDSон перестает отслеживать время с момента запуска оболочки,
mikeserv
1
@chepner - хорошо, конечно, но это не удерживает время оболочки снова. не поймите меня неправильно - я проголосовал за это, потому что это хороший ответ - но я думаю, что переопределение интерактивной оболочки $SECONDSдля каждого приглашения может вызвать неожиданное поведение. любая другая функция оболочки, которая может использовать ее по любой причине, связанной с оценкой времени выполнения, будет работать неправильно.
mikeserv
4
PS1[3]=$SECONDS
PS1='${PS1[!(PS1[1]=!1&(PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600))
   ]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]/60%60),  ${PS1[3]})):${PS1[1
   ]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]%60),     ${PS1[3]})):${PS1[1
   ]#${PS1[3]%%*??}0}$((PS1[3]=(SECONDS),       ${PS1[3]})):'$PS1

Это обрабатывает форматирование вычислением - поэтому, хотя оно расширяется в несколько раз, оно не выполняет никаких подоболочек или каналов.

Он просто обрабатывается $PS1как массив и использует более высокие индексы для хранения / вычисления любого / всех необходимых состояний между запросами. Никакое другое состояние оболочки не затрагивается.

00:00:46:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:00:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:43:[mikeserv@desktop tmp]$ sleep 10
00:00:33:[mikeserv@desktop tmp]$ sleep 10
00:00:15:[mikeserv@desktop tmp]$
00:00:15:[mikeserv@desktop tmp]$
00:00:02:[mikeserv@desktop tmp]$
00:02:27:[mikeserv@desktop tmp]$

Я могу немного сломать это, может быть ...

Сначала сохраните текущее значение $SECONDS:

PS1[3]=$SECONDS

Затем определите, $PS1[0]чтобы быть саморекурсивным таким образом, чтобы всегда устанавливать правильные значения $PS1[1-3]при одновременной самореференции. Чтобы получить эту часть, вы должны рассмотреть порядок, в котором вычисляются выражения shell-math. Самое главное, что shell-math всегда является последним заказом для shell-math. Прежде всего, оболочка расширяет значения. Таким образом, вы можете ссылаться на старое значение для переменной оболочки в математическом выражении после присвоения его с помощью $.

Вот простой пример:

x=10; echo "$(((x+=5)+$x+x))" "$x"

40 15

Оболочка будет оценивать этот оператор, сначала подставляя значение $xвезде, где используется $ссылка со знаком доллара, и поэтому выражение становится:

(x+=5)+10+x

... затем оболочка добавляет 5 к значению, $xа затем расширяет все выражение до x+10+x, сохраняя при этом только фактически назначенное значение в ссылочной переменной. Таким образом, расширенное значение математического выражения равно 40, но окончательное значение $xравно 15.

Это в основном то, как $PS1работает уравнение, за исключением того, что в индексах массива используется дополнительный уровень математического расширения / оценки.

PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'

Я не совсем уверен, почему я выбрал использование PS1[1]=!1там - я думаю, что это была просто глупая эстетика - но это присваивает 0 для $PS1[1]расширения при замене параметров. Значение побитового И для 0 и всего остального всегда будет 0, но оно не замыкается накоротко, как логическое значение &&, когда самый левый первичный элемент равен 0, и поэтому выражение в скобках по-прежнему вычисляется каждый раз. Это важно, конечно, потому что в этом первом элипсисе установлены начальные значения $PS1[2,3].

В любом случае, $PS1[1]здесь гарантируется, что он будет равен 0, даже если он был подделан в промежутках между быстрыми розыгрышами. В скобках есть ...

PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600

... $PS1[2]присваивается разность $PS1[3]и $SECONDS, и $PS1[3]присваивается частное этого значения и 3600. Все значения здесь инициализируются. И так:

${PS1[1]#${PS1[3]%%*??}0}

... если в нем хотя бы две цифры, $PS1[3]то внутреннее расширение равно нулю, и поскольку мы знаем, что $PS1[1]это 0, то если $PS1[3]можно заменить на ничто, то есть, в $PS1[1]противном случае оно расширяется до своего значения. Таким образом, только однозначные значения для каждой итерации $PS1[3]назначений будут расширять начальный ноль, и $PS1[3]он сам расширяется по модулю 60 сразу после этого, при этом одновременно присваивается следующее последовательно меньшее значение для каждого из часов, минут, секунд.

Промывайте и повторяйте до последней итерации, когда она $PS1[3]будет перезаписана, с текущим значением, $SECONDSчтобы его можно было сравнить с $SECONDSеще раз при следующем отображении подсказки.

mikeserv
источник
1

Лучшее решение, которое я нашел до сих пор, это: https://github.com/jichu4n/bash-command-timer

Который печатает [ 1s011 | May 25 15:33:44 BST ]или истекшее время на правой стороне после выполненной команды, так что это не загромождает вас PS1.

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

SEBS
источник