Mensaje de PS1 para mostrar el tiempo transcurrido

10

Actualmente lo uso para mostrar la hora actual en mi indicador de bash:

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

20:42:23 ~>

¿Es posible mostrar el tiempo transcurrido desde la solicitud anterior? Como:

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

Esto no tiene nada en común con ¿Es posible cambiar la PS1 periódicamente por un script en segundo plano?

BurlasDart
fuente
No, no hay respuesta en esa publicación y espero que la solicitud cambie solo cuando se muestre una nueva solicitud.
TeasingDart
Realmente no hay una manera factible de hacer lo que pides, no.
DopeGhoti
1
Es factible si el valor mostrado es estático (la pregunta de OP no parecía permitir eso). El tiempo transcurrido podría mantenerse guardando el tiempo de época del tiempo anterior en una variable de shell. Sin embargo, implementarlo parece mucho trabajo (aproximadamente una hora, tal vez alguien proporcionará una solución más simple de lo que tengo en mente). Esta pregunta sería de gran ayuda.
Thomas Dickey

Respuestas:

10

Una forma de hacerlo sería utilizar la función PROMPT_COMMAND de bash para ejecutar el código que modifica PS1. La siguiente función es una versión actualizada de mi envío original; éste usa dos variables de entorno menos y las antepone con "_PS1_" para tratar de evitar alterar variables existentes.

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)

Ponga eso en su .bash_profile para que las cosas comiencen.

Tenga en cuenta que debe escribir con bastante rapidez para que el sleepparámetro coincida con el parámetro de solicitud: el tiempo realmente es la diferencia entre las solicitudes, incluido el tiempo que le lleva escribir el 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 ~>

Adición tardía:

Basado en la respuesta ahora eliminada de @Cyrus, aquí hay una versión que no satura el entorno con variables adicionales:

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

Adición extra tardía:

A partir de la versión 4.2 de bash ( echo $BASH_VERSION), puede evitar las datellamadas externas con una nueva cadena de formato printf; reemplazar las $(date +%s)piezas con $(printf '%(%s)T' -1). A partir de la versión 4.3 , puede omitir el -1parámetro para confiar en el comportamiento "sin argumento significa ahora ".

Jeff Schaller
fuente
Esto está muy cerca. Funciona cuando copio / pego desde un indicador de bash, pero cuando intenté agregarlo a mi .bashrc imprime "1451424431: comando no encontrado"
TeasingDart
tal vez un poco demasiado copiado / pegado?
Jeff Schaller
Esta última versión funcionó, ¡exactamente lo que quería! Creo que tuvo algo que ver con mi trampa para establecer el color del texto después de la solicitud. Gracias.
TeasingDart
cuando lo reinicia $SECONDSdeja de rastrear el tiempo desde que se inició el shell,
mikeserv
1
@chepner: bueno, claro, pero no mantiene el tiempo del shell nunca más. no me malinterpreten, lo voté porque es una buena respuesta, pero creo que redefinir un shell interactivo $SECONDSpara cada mensaje puede generar comportamientos inesperados. cualquier otra función de shell que pueda usarla por cualquier motivo asociada con la evaluación del tiempo de ejecución se comportará mal.
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

Esto maneja el formato por cálculo, por lo tanto, si bien se expande varias veces, no hace subcapas ni tuberías.

Simplemente se trata $PS1como una matriz y utiliza los índices más altos para almacenar / calcular cualquier / todo estado necesario entre las indicaciones. Ningún otro estado de shell se ve afectado.

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

Puedo desglosar un poco tal vez ...

Primero, guarde el valor actual de $SECONDS:

PS1[3]=$SECONDS

A continuación, defina $PS1[0]ser auto recursivo de una manera que siempre establezca los valores correctos a la $PS1[1-3]vez que autorreferencia simultáneamente. Para obtener esta parte, debe considerar el orden en que se evalúan las expresiones matemáticas de shell. Lo más importante, shell-math es siempre el último orden del día para shell-math. Antes que nada, el shell expande los valores. De esta manera, puede hacer referencia a un valor antiguo para una variable de shell en una expresión matemática después de asignarlo mediante $.

Aquí hay un ejemplo simple primero:

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

40 15

El shell evaluará esa declaración sustituyendo primero el valor de $xdonde sea que $se use la referencia de signo de dólar, y entonces la expresión se convierte en:

(x+=5)+10+x

... luego el shell agrega 5 al valor de $xy luego expande toda la expresión x+10+x, mientras que retiene solo el valor asignado en la variable de referencia. Y entonces el valor expandido de la expresión matemática es 40, pero el valor final de $xes 15.

Así es en gran medida cómo funciona la $PS1ecuación también, excepto que hay un nivel adicional de expansión / evaluación matemática explotado en los índices de la matriz.

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

No estoy realmente seguro de por qué elegí usar PS1[1]=!1allí, supongo que probablemente fue solo una estética tonta, pero esto asigna 0 a la $PS1[1]vez que lo expande para la sustitución de parámetros. El valor de un AND bit a bit para 0 y cualquier otra cosa siempre será 0, pero no se cortocircuita como lo hace un booleano &&cuando el primario más a la izquierda es 0 y, por lo tanto, la expresión entre paréntesis aún se evalúa cada vez. Eso es importante, por supuesto, porque esa primera elipsis es donde se establecen los valores iniciales para $PS1[2,3].

De todos modos, $PS1[1]aquí se asegura que sea 0 incluso si se manipula con los sorteos rápidos. Entre paréntesis hay ...

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

... $PS1[2]se le asigna la diferencia de $PS1[3]y $SECONDS, y $PS1[3]se le asigna el cociente de ese valor y 3600. Todos los valores se inicializan aquí. Y entonces:

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

... si hay al menos dos dígitos en $PS1[3]la expansión interna, entonces es nula, y como sabemos que $PS1[1]es 0, entonces si $PS1[3]se puede sustituir por nada, entonces también $PS1[1]se expande a su valor. De esta manera, solo los valores de un solo dígito para cada iteración de $PS1[3]asignaciones expandirán un cero inicial, y en $PS1[3]sí mismo se expandirá el módulo 60 inmediatamente después mientras se le asigna simultáneamente el siguiente valor sucesivamente más pequeño para cada una de las horas, minutos y segundos.

Enjuague y repita, hasta que $PS1[3]se sobrescriba la última iteración con el valor actual de, de $SECONDSmodo que pueda compararse $SECONDSuna vez más cuando se dibuje nuevamente la solicitud.

mikeserv
fuente
1

La mejor solución que encontré hasta ahora es esta: https://github.com/jichu4n/bash-command-timer

Que imprime [ 1s011 | May 25 15:33:44 BST ]también conocido como el tiempo transcurrido en el lado derecho después del comando ejecutado, por lo que no satura tu PS1.

Todo el formato de cadena y hora es configurable. Incluso el color y la precisión son configurables. Sé que puede ser un poco demasiado para un minimalista, pero es genial.

sebs
fuente