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 $PS1
di 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 $x
del $
dollaro, quindi l'espressione diventa:
(x+=5)+10+x
... quindi la shell aggiunge 5 al valore di $x
e 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' $PS1
equazione, 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]=!1
lì - 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 $SECONDS
modo che possa essere confrontato $SECONDS
ancora una volta quando viene visualizzato il prompt successivo.