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 pelo cálculo - portanto, embora se expanda várias vezes, não faz subcascas ou tubos.
Ele apenas trata $PS1
como uma matriz e usa os índices mais altos para armazenar / calcular todo / qualquer estado necessário entre os 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 dividir 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 ao $PS1[1-3]
mesmo tempo em que se auto-referencia. Para obter essa parte, você deve considerar a ordem em que as expressões shell-math são avaliadas. Mais importante, shell-math é sempre a última ordem de negócios para shell-math. Antes de tudo, o shell expande valores. Dessa maneira, você pode fazer referência a um valor antigo para uma variável de shell em uma expressão matemática depois de atribuí-la 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
onde a $
referência do cifrão é usada e, portanto, a expressão se torna:
(x+=5)+10+x
... então o shell adiciona 5 ao valor de $x
e depois expande toda a expressão para x+10+x
, mantendo apenas o valor realmente atribuído na variável de referência. Portanto, o valor expandido da expressão matemática é 40, mas o valor final de $x
é 15.
É assim também que a $PS1
equação funciona, exceto que há um nível adicional de expansão / avaliação matemática explorada nos índices da matriz.
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
Não sei ao certo por que escolhi usar PS1[1]=!1
lá - acho que provavelmente era apenas uma estética boba - mas isso atribui 0 a $PS1[1]
enquanto o expande para substituição de parâmetros. O valor de um AND bit a bit para 0 e qualquer outra coisa sempre será 0, mas não funciona como um booleano &&
quando o primário mais à esquerda é 0 e, portanto, a expressão entre parênteses ainda é avaliada todas as vezes. Isso é importante, é claro, porque nessa primeira elipse é onde $PS1[2,3]
são definidos os valores iniciais .
De qualquer forma, $PS1[1]
aqui é garantido que seja 0, mesmo se for violado entre os sorteios imediatos. Dentro dos parênteses lá ...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
... $PS1[2]
é atribuída 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 entao:
${PS1[1]#${PS1[3]%%*??}0}
... se houver pelo menos dois dígitos $PS1[3]
, a expansão interna será nula e, como sabemos que $PS1[1]
é 0, se ela $PS1[3]
puder ser substituída por nada, também $PS1[1]
será expandida para seu valor. Dessa maneira, somente os valores de um dígito para cada iteração de $PS1[3]
atribuições expandirão um zero inicial, e $PS1[3]
ele próprio será expandido no módulo 60 imediatamente depois, sendo simultaneamente atribuído o próximo valor sucessivamente menor para cada hora, minutos e segundos.
Enxágüe e repita, até a última iteração, quando $PS1[3]
é substituída pelo valor atual de, $SECONDS
para que possa ser comparada $SECONDS
mais uma vez quando o prompt for desenhado.