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 $PS1
como 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 $x
donde 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 $x
y 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 $x
es 15.
Así es en gran medida cómo funciona la $PS1
ecuació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]=!1
allí, 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 $SECONDS
modo que pueda compararse $SECONDS
una vez más cuando se dibuje nuevamente la solicitud.