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
ще раз, коли наступне звернення буде звернено.