PS1 richiede di mostrare il tempo trascorso


10

Attualmente lo uso per visualizzare l'ora corrente nel mio prompt di bash:

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

20:42:23 ~>

È possibile visualizzare il tempo trascorso dal prompt precedente? Ad esempio:

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

Questo non ha nulla in comune con È possibile cambiare periodicamente la PS1 con uno script in background?



No, non c'è risposta in quel post e mi aspetto che il prompt cambi solo quando viene visualizzato un nuovo prompt.
TeasingDart

Non c'è davvero un modo fattibile per fare ciò che chiedi, no.
DopeGhoti,

1
È fattibile se il valore visualizzato è statico (la domanda dell'OP non sembra consentirlo). Il tempo trascorso potrebbe essere mantenuto salvando il tempo di epoca della volta precedente in una variabile shell. L'implementazione sembra un sacco di lavoro (circa un'ora - forse qualcuno fornirà una soluzione più semplice di quello che ho in mente). Questa domanda sarebbe utile.
Thomas Dickey,

Risposte:


10

Un modo per farlo sarebbe usare la funzione PROMPT_COMMAND di bash per eseguire il codice che modifica PS1. La funzione seguente è una versione aggiornata della mia presentazione originale; questo usa due variabili d'ambiente in meno e le prefigura con "_PS1_" per cercare di evitare il blocco delle variabili esistenti.

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)

Inseriscilo nel tuo .bash_profile per avviare le cose.

Si noti che è necessario digitare abbastanza rapidamente per far corrispondere il sleepparametro al parametro prompt: il tempo è davvero la differenza tra i prompt, incluso il tempo impiegato per digitare il comando.

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

Aggiunta tardiva:

Basato sulla risposta ora cancellata di @Cyrus, ecco una versione che non ingombra l'ambiente con variabili extra:

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

Aggiunta tardiva extra:

A partire da bash versione 4.2 ( echo $BASH_VERSION), è possibile evitare le datechiamate esterne con una nuova stringa di formato printf; sostituire i $(date +%s)pezzi con $(printf '%(%s)T' -1). A partire dalla versione 4.3 , è possibile omettere il -1parametro per fare affidamento sul comportamento "nessun argomento significa ora ".


Questo è molto vicino. Funziona quando copio / incolla da un prompt di bash, ma quando ho provato ad aggiungerlo al mio .bashrc stampa "1451424431: comando non trovato"
TeasingDart

forse un po 'troppo è stato copiato / incollato?
Jeff Schaller

Quest'ultima versione ha funzionato, esattamente quello che volevo! Penso che abbia avuto qualcosa a che fare con la mia trappola per impostare il colore del testo dopo il prompt. Grazie.
TeasingDart

quando lo ripristini $SECONDScessa di tenere traccia del tempo
trascorso

1
@chepner - beh, certo, ma non mantiene mai più il tempo della shell. non fraintendetemi - l'ho votato perché è una buona risposta - ma penso che ridefinire la shell interattiva $SECONDSper ogni prompt possa suscitare comportamenti inaspettati. qualsiasi altra funzione della shell che potrebbe usarla per qualsiasi motivo associato alla valutazione del runtime si comporterà in modo errato.
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

Questo gestisce la formattazione mediante calcolo, quindi, sebbene si espanda più volte, non esegue sottotitoli o pipe.

Si tratta solo $PS1di un array e utilizza gli indici più alti per memorizzare / calcolare qualsiasi / tutto lo stato necessario tra i prompt. Nessun altro stato della shell è interessato.

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

Posso romperlo un po 'forse ...

Innanzitutto, salva il valore corrente di $SECONDS:

PS1[3]=$SECONDS

Successivamente, definisci $PS1[0]auto-ricorsivo in un modo che imposterà sempre i valori giusti su $PS1[1-3]se stesso contemporaneamente all'autoreferenziazione. Per ottenere questa parte devi considerare l'ordine in cui vengono valutate le espressioni matematiche shell. Ancora più importante, shell-math è sempre l'ultimo ordine di affari per shell-math. Prima di tutto, la shell espande i valori. In questo modo è possibile fare riferimento a un vecchio valore per una variabile shell in un'espressione matematica dopo averlo assegnato utilizzando $.

Ecco un semplice esempio prima:

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

40 15

La shell valuterà tale affermazione sostituendo prima il valore del punto in cui viene utilizzato il riferimento del simbolo $xdel $dollaro, quindi l'espressione diventa:

(x+=5)+10+x

... quindi la shell aggiunge 5 al valore di $xe successivamente espande l'intera espressione x+10+x, mantenendo solo il valore effettivamente assegnato nella variabile di riferimento. Quindi il valore espanso dell'espressione matematica è 40, ma il valore finale di $xè 15.

Questo è in gran parte il modo in cui funziona anche l' $PS1equazione, tranne per il fatto che esiste un ulteriore livello di espansione / valutazione matematica sfruttato negli indici di array.

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

Non sono davvero sicuro del motivo per cui ho scelto di usarlo PS1[1]=!1lì - suppongo fosse probabilmente solo un'estetica sciocca - ma questo assegna 0 a $PS1[1]mentre lo espande per la sostituzione dei parametri. Il valore di AND bit a bit per 0 e qualsiasi altra cosa sarà sempre 0, ma non cortocircuita come fa un booleano &&quando il primario più a sinistra è 0 e quindi l'espressione tra parentesi viene comunque valutata ogni volta. Questo è importante, ovviamente, perché quella prima elipsis è dove $PS1[2,3]vengono impostati i valori iniziali per .

Ad ogni modo, $PS1[1]qui è garantito che è 0 anche se viene manomesso tra i disegni rapidi. Tra parentesi c'è ...

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

... $PS1[2]viene assegnata la differenza di $PS1[3]e $SECONDS, e $PS1[3]viene assegnato il quoziente di quel valore e 3600. Tutti i valori vengono qui inizializzati. E così:

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

... se ci sono almeno due cifre, $PS1[3]allora l'espansione interna è nulla, e poiché sappiamo che $PS1[1]è 0, allora se $PS1[3]può essere sostituito a nulla, così è $PS1[1]altrimenti viene espanso al suo valore. In questo modo solo i valori a una sola cifra per ogni iterazione di $PS1[3]assegnazioni espandono uno zero iniziale, e $PS1[3]viene esso stesso espanso modulo 60 immediatamente dopo, mentre contemporaneamente viene assegnato il valore successivo più piccolo per ciascuna di ore, minuti, secondi.

Risciacquare e ripetere, fino all'ultima iterazione quando $PS1[3]viene sovrascritto con il valore corrente in $SECONDSmodo che possa essere confrontato $SECONDSancora una volta quando viene visualizzato il prompt successivo.


1

La migliore soluzione che ho trovato finora è questa: https://github.com/jichu4n/bash-command-timer

Che stampa [ 1s011 | May 25 15:33:44 BST ]alias il tempo trascorso sul lato destro dopo il comando eseguito, quindi non ingombra la PS1.

L'intero formato di stringa e ora è configurabile. Anche il colore e la precisione sono configurabili. So che potrebbe essere un po 'troppo per alcuni minimalisti là fuori, ma è piuttosto bello.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.