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
Cela gère la mise en forme par calcul - donc, bien qu'il se développe plusieurs fois, il ne fait aucun sous-shell ou tuyau.
Il traite simplement $PS1
comme un tableau et utilise les indices supérieurs pour stocker / calculer tout / tous les états nécessaires entre les invites. Aucun autre état shell n'est affecté.
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]$
Je peux le décomposer un peu peut-être ...
Tout d'abord, enregistrez la valeur actuelle de $SECONDS
:
PS1[3]=$SECONDS
Ensuite, définissez $PS1[0]
comme auto-récursif d'une manière qui définira toujours les bonnes valeurs $PS1[1-3]
tout en se référençant simultanément. Pour obtenir cette partie, vous devez considérer l'ordre dans lequel les expressions shell-math sont évaluées. Plus important encore, le shell-math est toujours le dernier ordre du jour pour le shell-math. Avant tout, le shell développe les valeurs. De cette façon, vous pouvez référencer une ancienne valeur pour une variable shell dans une expression mathématique après l'avoir affectée à l'aide de $
.
Voici d'abord un exemple simple:
x=10; echo "$(((x+=5)+$x+x))" "$x"
40 15
Le shell évaluera cette déclaration en substituant d'abord la valeur de l' $x
endroit où la $
référence du signe dollar est utilisée, et ainsi l'expression devient:
(x+=5)+10+x
... puis le shell ajoute 5 à la valeur de $x
et étend ensuite l'expression entière à x+10+x
, tout en ne conservant que la valeur réellement affectée dans la variable de référence. Et donc la valeur développée de l'expression mathématique est 40, mais la valeur ultime de $x
est 15.
C'est en grande partie ainsi que fonctionne l' $PS1
équation, sauf qu'il existe un autre niveau d'expansion / évaluation mathématique exploité dans les indices de tableau.
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
Je ne sais pas vraiment pourquoi j'ai choisi de l'utiliser PS1[1]=!1
ici - je suppose que c'était probablement juste une esthétique stupide - mais cela attribue 0 à $PS1[1]
tout en le développant pour la substitution de paramètres. La valeur d'un AND au niveau du bit pour 0 et toute autre chose sera toujours 0, mais elle ne court-circuite pas comme le fait un booléen &&
lorsque le primaire le plus à gauche est 0 et donc l'expression entre parenthèses est toujours évaluée à chaque fois. C'est important, bien sûr, parce que cette première élipse est l'endroit où les valeurs initiales de $PS1[2,3]
sont définies.
Quoi qu'il en soit, $PS1[1]
est ici assuré d'être égal à 0 même s'il est falsifié avec / entre les tirages d'invite. Entre parenthèses, il ...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
... $PS1[2]
se voit attribuer la différence de $PS1[3]
et $SECONDS
, et $PS1[3]
le quotient de cette valeur et 3600. Toutes les valeurs sont ici initialisées. Et donc:
${PS1[1]#${PS1[3]%%*??}0}
... s'il y a au moins deux chiffres, $PS1[3]
alors l'expansion interne est nulle, et parce que nous savons que $PS1[1]
0, alors si elle $PS1[3]
peut être remplacée par rien, il en est de même $PS1[1]
autrement elle est développée à sa valeur. De cette façon, seules les valeurs à un chiffre pour chaque itération d' $PS1[3]
affectations développeront un zéro de tête, et $PS1[3]
elle-même est étendue modulo 60 immédiatement après tout en étant simultanément affectée à la prochaine valeur successivement plus petite pour chacune des heures, minutes et secondes.
Rincez et répétez, jusqu'à ce que la dernière itération $PS1[3]
soit écrasée avec la valeur actuelle de $SECONDS
afin qu'elle puisse être comparée $SECONDS
une fois de plus lorsque l'invite est ensuite dessinée.