PS1 prompt para mostrar o tempo decorrido

9

Eu atualmente uso isso para exibir a hora atual no meu prompt bash:

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

20:42:23 ~>

É possível exibir o tempo decorrido desde o aviso anterior? Tais como:

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

Isso não tem nada em comum com É possível alterar o PS1 periodicamente por um script em segundo plano?

    
por TeasingDart 29.12.2015 / 21:46

3 respostas

9

Uma maneira de fazer isso seria usar o recurso PROMPT_COMMAND do bash para executar o código que modifica o PS1. A função abaixo é uma versão atualizada da minha submissão original; este usa duas variáveis de ambiente a menos e prefixa-as com "_PS1_" para tentar evitar a supressão de variáveis 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)

Coloque isso no seu .bash_profile para iniciar as coisas.

Note que você precisa digitar rapidamente para obter o parâmetro sleep para corresponder ao parâmetro prompt - a hora é realmente a diferença entre os prompts, incluindo o tempo que você leva para digitar o 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 ~>

Adição tardia:

Com base na resposta agora excluída do @Cyrus, aqui está uma versão que não atravessa o ambiente com variáveis extras:

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

Adição extra tardia:

Começando na versão bash 4.2 ( echo $BASH_VERSION ), você pode evitar as chamadas date externas com uma nova string de formato printf; substitua as $(date +%s) partes por $(printf '%(%s)T' -1) . A partir da versão 4.3 , você pode omitir a% parâmetro-1 para confiar no comportamento "nenhum argumento significa agora ".

    
por 29.12.2015 / 22:13
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

Isso lida com a formatação por cálculo - assim, enquanto ele expande várias vezes, ele não faz nenhum subshell ou pipe.

Ele trata apenas $PS1 como uma matriz e usa os índices mais altos para armazenar / calcular qualquer / todo estado necessário entre prompts. Nenhum outro estado do shell é afetado.

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

Eu posso dividi-lo um pouco, talvez ...

Primeiro, salve o valor atual de $SECONDS :

PS1[3]=$SECONDS

Em seguida, defina $PS1[0] para ser auto-recursivo de uma maneira que sempre defina os valores corretos para $PS1[1-3] e, ao mesmo tempo, faça a auto-referência. Para obter essa parte, você deve considerar a ordem em que as expressões shell-math são avaliadas. Mais importante ainda, a matemática de shell é sempre a última ordem de trabalho para o shell-math. Antes de tudo, o shell expande os valores. Dessa forma, você pode referenciar um valor antigo para uma variável de shell em uma expressão matemática depois de atribuí-lo usando $ .

Aqui está um exemplo simples primeiro:

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

O shell avaliará essa instrução substituindo primeiro o valor de $x sempre que a referência $ dollar-sign for usada e, assim, a expressão se tornar:

(x+=5)+10+x

... então o shell adiciona 5 ao valor de $x e depois expande a expressão inteira para x+10+x , mantendo apenas o valor atribuído na variável de referência. E assim o valor expandido da expressão matemática é 40, mas o valor final de $x é 15.

Isso é em grande parte como a equação $PS1 também funciona, exceto que existe um nível adicional de expansão / avaliação matemática explorada nos índices da matriz.

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

Eu não sei ao certo por que escolhi usar PS1[1]=!1 - acho que provavelmente foi apenas uma estética boba - mas isso atribui 0 a $PS1[1] enquanto expande para substituição de parâmetro. O valor de um bit a bit E para 0 e qualquer outra coisa sempre será 0, mas não entra em curto-circuito quando um% booleano && faz quando o primário mais à esquerda é 0 e a expressão entre parênteses ainda é avaliada a cada vez. Isso é importante, é claro, porque a primeira elipse é onde os valores iniciais de $PS1[2,3] são definidos.

De qualquer forma, $PS1[1] é garantido como 0 mesmo que seja adulterado com os empates. Dentro dos parênteses há ...

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

... $PS1[2] recebe a diferença de $PS1[3] e $SECONDS , e $PS1[3] é atribuído o quociente desse valor e 3600. Todos os valores são aqui inicializados. E assim:

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

... se houver pelo menos dois dígitos em $PS1[3] , então a expansão interna é nula, e porque sabemos que $PS1[1] é 0, então se $PS1[3] pode ser substituído por nada, então também é $PS1[1] else é expandido para seu valor. Deste modo, apenas valores de dígito único para cada iteração de atribuições $PS1[3] expandirão um zero à esquerda, e $PS1[3] é em si módulo expandido 60 imediatamente a seguir sendo atribuído simultaneamente o próximo valor sucessivamente menor para cada uma das horas, minutos, segundos.

Enxágue e repita, até a última iteração quando $PS1[3] for sobrescrito com o valor atual de $SECONDS , para que possa ser comparado a $SECONDS mais uma vez quando o prompt for desenhado a seguir.

    
por 30.12.2015 / 11:44
0

A melhor solução que encontrei até agora é a seguinte: link

Que imprime [ 1s011 | May 25 15:33:44 BST ] aka o tempo decorrido no lado direito após o comando executado, para que ele não fique cheio do PS1.

A string inteira e o formato de hora são configuráveis. Até a cor e a precisão são configuráveis. Eu sei que pode ser um pouco demais para alguns minimalistas, mas é bem legal.

    
por 25.05.2018 / 16:36

Tags