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
Obsługuje formatowanie według obliczeń - więc, chociaż rozszerza się kilka razy, nie robi żadnych podpowłok ani potoków.
Po prostu traktuje $PS1
jak tablicę i wykorzystuje wyższe indeksy do przechowywania / obliczania dowolnego / wszystkich niezbędnych stanów między podpowiedziami. Nie ma to wpływu na żaden inny stan powłoki.
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]$
Mogę to trochę zepsuć ...
Najpierw zapisz bieżącą wartość $SECONDS
:
PS1[3]=$SECONDS
Następnie zdefiniuj, $PS1[0]
aby był rekurencyjny w sposób, który zawsze ustawi odpowiednie wartości, $PS1[1-3]
a jednocześnie będzie zawierał odnośniki. Aby uzyskać tę część, musisz wziąć pod uwagę kolejność, w jakiej wyrażenia matematyczne są obliczane. Co najważniejsze, matematyka w powłoce jest zawsze ostatnim rodzajem biznesu dla matematyki w powłoce. Przede wszystkim powłoka rozszerza wartości. W ten sposób możesz odwoływać się do starej wartości zmiennej powłoki w wyrażeniu matematycznym po przypisaniu jej za pomocą $
.
Oto pierwszy prosty przykład:
x=10; echo "$(((x+=5)+$x+x))" "$x"
40 15
Powłoka oceni tę instrukcję, najpierw podstawiając wartość $x
wszędzie tam, gdzie $
używane jest odwołanie do znaku dolara, a zatem wyrażenie staje się:
(x+=5)+10+x
... wtedy powłoka dodaje 5 do wartości, $x
a następnie rozwija całe wyrażenie x+10+x
, zachowując tylko faktycznie przypisaną wartość w zmiennej referencyjnej. Zatem rozszerzona wartość wyrażenia matematycznego wynosi 40, ale ostateczna wartość $x
to 15.
Tak w dużej mierze $PS1
działa również równanie, z tym wyjątkiem, że w indeksach tablicowych wykorzystywany jest dalszy poziom rozszerzenia / oceny matematyki.
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
Nie jestem do końca pewien, dlaczego zdecydowałem się PS1[1]=!1
tam użyć - wydaje mi się, że była to po prostu głupia estetyka - ale przypisuje to 0 $PS1[1]
podczas rozszerzania go do podstawiania parametrów. Wartość bitowego AND dla 0 i cokolwiek innego zawsze będzie wynosić 0, ale nie zwiera się jak wartość logiczna &&
, gdy skrajnie lewe pierwsze to 0, więc wyrażenie w nawiasie wciąż jest oceniane za każdym razem. Jest to oczywiście ważne, ponieważ w pierwszej elipsie $PS1[2,3]
ustawiane są wartości początkowe .
W każdym razie $PS1[1]
zapewnione jest, że wynosi 0, nawet jeśli jest sfałszowane w / między kolejnymi losowaniami. W nawiasach znajdują się ...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
... $PS1[2]
przypisano różnicę $PS1[3]
i $SECONDS
oraz $PS1[3]
przypisano mu iloraz tej wartości i 3600. Wszystkie wartości są tutaj inicjowane. A więc:
${PS1[1]#${PS1[3]%%*??}0}
... jeśli są co najmniej dwie cyfry, $PS1[3]
wówczas wewnętrzne rozwinięcie jest zerowe, a ponieważ wiemy, że $PS1[1]
wynosi 0, to jeśli $PS1[3]
można je zastąpić niczym, to także jest $PS1[1]
ono rozwinięte do wartości. W ten sposób tylko wartości jednocyfrowe dla każdej iteracji $PS1[3]
przypisań zwiększą początkowe zero, a $PS1[3]
samo jest bezpośrednio rozszerzone modulo 60 zaraz po tym, jednocześnie przypisując kolejną kolejno mniejszą wartość dla każdej godziny, minuty, sekundy.
Opłucz i powtórz, aż do ostatniej iteracji, w której $PS1[3]
zostanie nadpisana w / bieżąca wartość, $SECONDS
aby można ją było porównać z $SECONDS
jeszcze raz, gdy zostanie narysowany monit.