PS1-Aufforderung zur Anzeige der verstrichenen Zeit


10

Ich verwende dies derzeit, um die aktuelle Uhrzeit in meiner Bash-Eingabeaufforderung anzuzeigen:

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

20:42:23 ~>

Ist es möglich, die seit der vorherigen Eingabeaufforderung verstrichene Zeit anzuzeigen? Sowie:

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

Dies hat nichts mit zu tun. Ist es möglich, die PS1 regelmäßig durch ein Skript im Hintergrund zu ändern?



Nein, in diesem Beitrag gibt es keine Antwort und ich erwarte, dass sich die Eingabeaufforderung nur ändert, wenn eine neue Eingabeaufforderung angezeigt wird.
TeasingDart

Es gibt keinen wirklich praktikablen Weg, um das zu tun, was Sie verlangen, nein.
DopeGhoti

1
Es ist möglich, wenn der angezeigte Wert statisch ist (die Frage von OP schien dies nicht zuzulassen). Die verstrichene Zeit kann beibehalten werden, indem die Epochenzeit der vorherigen Zeit in einer Shell-Variablen gespeichert wird. Die Implementierung scheint jedoch eine Menge Arbeit zu sein (ungefähr eine Stunde - vielleicht bietet jemand eine einfachere Lösung als ich es mir vorgestellt habe). Diese Frage wäre hilfreich.
Thomas Dickey

Antworten:


10

Eine Möglichkeit wäre, die PROMPT_COMMAND-Funktion von bash zu verwenden, um Code auszuführen, der PS1 modifiziert. Die folgende Funktion ist eine aktualisierte Version meiner ursprünglichen Einreichung. Dieser verwendet zwei Umgebungsvariablen weniger und stellt ihnen "_PS1_" voran, um zu vermeiden, dass vorhandene Variablen überlastet werden.

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)

Fügen Sie das in Ihr .bash_profile ein, um die Dinge in Gang zu bringen.

Beachten Sie, dass Sie ziemlich schnell eingeben müssen, damit der sleepParameter mit dem Eingabeaufforderungsparameter übereinstimmt. Die Zeit ist wirklich der Unterschied zwischen den Eingabeaufforderungen, einschließlich der Zeit, die Sie zum Eingeben des Befehls benötigen.

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 ~>

Späte Hinzufügung:

Basierend auf der jetzt gelöschten Antwort von @Cyrus ist hier eine Version, die die Umgebung nicht mit zusätzlichen Variablen überfüllt:

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))\""

Extra späte Zugabe:

Ab Bash-Version 4.2 ( echo $BASH_VERSION) können Sie externe dateAufrufe mit einer neuen Zeichenfolge im printf-Format vermeiden . Ersetzen Sie die $(date +%s)Teile durch $(printf '%(%s)T' -1). Ab Version 4.3 können Sie den -1Parameter weglassen , um sich auf das Verhalten "Kein Argument bedeutet jetzt " zu verlassen.


Das ist ganz nah. Es funktioniert, wenn ich von einer Bash-Eingabeaufforderung kopiere / einfüge, aber als ich versuchte, es zu meiner .bashrc hinzuzufügen, wird "1451424431: Befehl nicht gefunden"
ausgegeben

Vielleicht wurde etwas zu viel kopiert / eingefügt?
Jeff Schaller

Diese letzte Version hat funktioniert, genau das, was ich wollte! Ich denke, es hatte etwas mit meiner Falle zu tun, die Textfarbe nach der Eingabeaufforderung festzulegen. Vielen Dank.
TeasingDart

Wenn Sie zurücksetzen $SECONDS, wird die Zeit seit dem Start der Shell nicht mehr verfolgt.
MikeServ

1
@chepner - na klar, aber es hält die Zeit der Shell nie wieder. Versteh mich nicht falsch - ich habe dies positiv bewertet, weil es eine gute Antwort ist - aber ich denke, dass die Neudefinition einer interaktiven Shell $SECONDSfür jede Eingabeaufforderung wahrscheinlich unerwartete Verhaltensweisen hervorruft. Jede andere Shell-Funktion, die sie aus irgendeinem Grund im Zusammenhang mit der Auswertung der Laufzeit verwendet, verhält sich schlecht.
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

Dies behandelt die Formatierung durch Berechnung. Während sie mehrmals erweitert wird, werden keine Unterschalen oder Pipes ausgeführt.

Es wird nur $PS1als Array behandelt und verwendet die höheren Indizes, um alle erforderlichen Zustände zwischen den Eingabeaufforderungen zu speichern / zu berechnen. Kein anderer Shell-Status ist betroffen.

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]$

Ich kann es vielleicht ein wenig aufschlüsseln ...

Speichern Sie zunächst den aktuellen Wert von $SECONDS:

PS1[3]=$SECONDS

Definieren Sie $PS1[0]als Nächstes, dass Sie selbstrekursiv sind und dabei immer die richtigen Werte festlegen, $PS1[1-3]während Sie sich gleichzeitig selbst referenzieren. Um diesen Teil zu erhalten, müssen Sie die Reihenfolge berücksichtigen, in der Shell-Math-Ausdrücke ausgewertet werden. Am wichtigsten ist, dass Shell-Math immer die letzte Aufgabe für Shell-Math ist. Vor allem erweitert die Shell die Werte. Auf diese Weise können Sie einen alten Wert für eine Shell-Variable in einem mathematischen Ausdruck referenzieren, nachdem Sie ihn mithilfe von zugewiesen haben $.

Hier ist zunächst ein einfaches Beispiel:

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

40 15

Die Shell wertet diese Anweisung aus, indem sie zuerst den Wert der Stelle ersetzt, an der $xdie $Dollarzeichenreferenz verwendet wird. Der Ausdruck lautet also:

(x+=5)+10+x

... dann addiert die Shell 5 zum Wert von $xund erweitert anschließend den gesamten Ausdruck auf x+10+x, wobei nur der tatsächlich zugewiesene Wert in der Referenzvariablen beibehalten wird. Der erweiterte Wert des mathematischen Ausdrucks ist also 40, aber der endgültige Wert von $xist 15.

So funktioniert die $PS1Gleichung größtenteils auch, außer dass in den Array-Indizes eine weitere Ebene der mathematischen Erweiterung / Bewertung ausgenutzt wird.

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

Ich bin mir nicht sicher, warum ich mich für die Verwendung PS1[1]=!1dort entschieden habe - ich denke, es war wahrscheinlich nur eine dumme Ästhetik -, aber dies weist 0 zu, $PS1[1]während es für die Parametersubstitution erweitert wird. Der Wert eines bitweisen UND für 0 und alles andere ist immer 0, aber er schließt nicht wie ein Boolescher Wert kurz, &&wenn der am weitesten links stehende Primärwert 0 ist, und daher wird der Ausdruck in Klammern jedes Mal ausgewertet. Das ist natürlich wichtig, da in dieser ersten Elipse die Anfangswerte für $PS1[2,3]festgelegt werden.

Wie auch immer, $PS1[1]hier ist versichert, 0 zu sein, selbst wenn es zwischen sofortigen Zügen manipuliert wird. In den Klammern steht ...

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

... $PS1[2]ist der Unterschied von zugewiesen $PS1[3]und $SECONDS, und $PS1[3]ist der Quotient aus diesem Wert und 3600. Alle Werte werden hier initialisiert zugewiesen. Und so:

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

... wenn es mindestens zwei Ziffern gibt, $PS1[3]dann ist die innere Erweiterung dort null, und weil wir wissen, dass sie $PS1[1]0 ist, $PS1[3]kann sie, wenn sie durch nichts ersetzt werden kann, auch $PS1[1]auf ihren Wert erweitert werden. Auf diese Weise erweitern nur einstellige Werte für jede Iteration von $PS1[3]Zuweisungen eine führende Null und werden $PS1[3]unmittelbar danach modulo 60 erweitert, während gleichzeitig der nächste sukzessive kleinere Wert für jede Stunde, Minute, Sekunde zugewiesen wird.

Spülen und wiederholen, bis die letzte Iteration $PS1[3]mit dem aktuellen Wert von überschrieben wird, $SECONDSdamit sie $SECONDSbeim nächsten Zeichnen der Eingabeaufforderung erneut verglichen werden kann .


1

Die beste Lösung, die ich bisher gefunden habe, ist folgende: https://github.com/jichu4n/bash-command-timer

Was [ 1s011 | May 25 15:33:44 BST ]auch immer die verstrichene Zeit auf der rechten Seite nach dem ausgeführten Befehl druckt , damit Sie PS1 nicht überladen.

Das gesamte Zeichenfolgen- und Zeitformat ist konfigurierbar. Auch die Farbe und die Präzision sind konfigurierbar. Ich weiß, dass es für einige Minimalisten da draußen ein bisschen viel sein könnte, aber es ist ziemlich cool.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.