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

Не існує насправді здійсненного способу зробити те, що ви просите, ні.
DopeGhoti

1
Це можливо, якщо відображене значення є статичним (питання ОП, здається, не дозволяє цього). Пройдений час можна підтримувати, зберігаючи час епохи попереднього часу в змінній оболонки. Але реалізація, здається, велика робота (хоча годину чи більше - можливо, хтось запропонує простіше рішення, ніж те, що я маю на увазі). Це питання було б корисним.
Томас Дікі

Відповіді:


10

Одним із способів зробити це буде використання функції PROMPT_COMMAND bash для виконання коду, що модифікує 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]при одночасному самовіднесенні. Щоб отримати цю частину, ви повинні врахувати порядок, в якому оцінюються вирази оболонки. Найголовніше, що шал-математика - це завжди останній порядок ведення бізнесу для шлаг-математики. Перш за все, оболонка розширює значення. Таким чином, ви можете посилатися на старе значення для змінної оболонки в математичному виразі після призначення їх за допомогою $.

Ось перший простий приклад:

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]розширення для заміни параметрів. Значення побітового AND для 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]буде перезаписано w / поточне значення, $SECONDSтак що воно може бути порівняно з $SECONDSще раз, коли наступне звернення буде звернено.


1

Найкраще рішення, яке я знайшов поки що, це: https://github.com/jichu4n/bash-command-timer

Який друкує [ 1s011 | May 25 15:33:44 BST ]час, що минув у правій частині після виконаної команди, тому він не захаращує вас PS1.

Весь формат рядка та часу налаштовується. Навіть колір і точність налаштовуються. Я знаю, що це може бути трохи для деяких мінімалістів там, але це досить круто.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.