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
Điều này xử lý định dạng bằng tính toán - vì vậy, trong khi nó mở rộng nhiều lần, nó không thực hiện bất kỳ lớp con hoặc đường ống nào.
Nó chỉ coi $PS1
là một mảng và sử dụng các chỉ số cao hơn để lưu trữ / tính toán bất kỳ / tất cả trạng thái cần thiết giữa các lời nhắc. Không có trạng thái vỏ khác bị ảnh hưởng.
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]$
Tôi có thể phá vỡ nó một chút có lẽ ...
Đầu tiên, lưu giá trị hiện tại của $SECONDS
:
PS1[3]=$SECONDS
Tiếp theo, xác định $PS1[0]
để tự đệ quy theo cách sẽ luôn đặt các giá trị đúng thành $PS1[1-3]
đồng thời tự tham chiếu. Để có được phần này, bạn phải xem xét thứ tự các biểu thức shell-math được ước tính. Quan trọng nhất, shell-math luôn là thứ tự kinh doanh cuối cùng cho shell-math. Trước tất cả, shell mở rộng các giá trị. Theo cách này, bạn có thể tham chiếu một giá trị cũ cho biến shell trong biểu thức toán học sau khi gán nó bằng cách sử dụng $
.
Đây là một ví dụ đơn giản đầu tiên:
x=10; echo "$(((x+=5)+$x+x))" "$x"
40 15
Shell sẽ đánh giá tuyên bố đó bằng cách thay thế giá trị của $x
bất cứ nơi nào $
tham chiếu ký hiệu đô la được sử dụng và do đó biểu thức trở thành:
(x+=5)+10+x
... Sau đó, shell thêm 5 vào giá trị của $x
và sau đó mở rộng toàn bộ biểu thức thành x+10+x
, trong khi chỉ giữ lại giá trị được gán thực sự trong biến tham chiếu. Và vì vậy, giá trị mở rộng của biểu thức toán học là 40, nhưng giá trị cuối cùng $x
là 15.
Đó phần lớn là cách $PS1
phương trình hoạt động tốt, ngoại trừ việc có thêm một mức độ mở rộng / đánh giá toán học được khai thác trong các chỉ số mảng.
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
Tôi không thực sự chắc chắn lý do tại sao tôi chọn sử dụng PS1[1]=!1
ở đó - tôi đoán có lẽ nó chỉ là thẩm mỹ ngớ ngẩn - nhưng điều này gán 0 cho $PS1[1]
trong khi mở rộng nó để thay thế tham số. Giá trị của bitwise AND cho 0 và bất cứ thứ gì khác sẽ luôn là 0, nhưng nó không bị đoản mạch như một boolean &&
khi giá trị chính bên trái là 0 và do đó biểu thức chính vẫn được đánh giá mỗi lần. Tất nhiên, đó là điều quan trọng, bởi vì elipsis đầu tiên là nơi đặt các giá trị ban đầu cho $PS1[2,3]
.
Dù sao, $PS1[1]
ở đây được đảm bảo là 0 ngay cả khi nó bị giả mạo w / giữa các lần rút thăm kịp thời. Trong ngoặc đơn có ...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
... $PS1[2]
được chỉ định sự khác biệt của $PS1[3]
và $SECONDS
, và $PS1[3]
được chỉ định thương số của giá trị đó và 3600. Tất cả các giá trị được khởi tạo ở đây. Và vì thế:
${PS1[1]#${PS1[3]%%*??}0}
... Nếu có ít nhất hai chữ số $PS1[3]
thì phần mở rộng bên trong không có giá trị và vì chúng ta biết $PS1[1]
là 0 nên nếu $PS1[3]
có thể được thay thế thành không có gì, $PS1[1]
thì nó cũng được mở rộng thành giá trị của nó. Theo cách này, chỉ các giá trị một chữ số cho mỗi lần lặp của $PS1[3]
bài tập sẽ mở rộng một số 0 đứng đầu và $PS1[3]
chính nó được mở rộng modulo 60 ngay sau đó trong khi được gán đồng thời giá trị nhỏ hơn tiếp theo cho mỗi giờ, phút, giây.
Rửa sạch và lặp lại, cho đến lần lặp cuối cùng khi $PS1[3]
được ghi đè lên w / giá trị hiện tại $SECONDS
để nó có thể được so sánh với $SECONDS
một lần nữa khi lời nhắc được vẽ tiếp theo.