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
Ini menangani pemformatan dengan kalkulasi - jadi, meskipun ia berkembang beberapa kali, ia tidak melakukan subshell atau pipa.
Itu hanya memperlakukan $PS1
sebagai array dan menggunakan indeks yang lebih tinggi untuk menyimpan / menghitung setiap / semua keadaan yang diperlukan antara prompt. Tidak ada kondisi shell lain yang terpengaruh.
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]$
Saya bisa memecahnya sedikit mungkin ...
Pertama, simpan nilai saat ini dari $SECONDS
:
PS1[3]=$SECONDS
Selanjutnya, definisikan $PS1[0]
untuk menjadi self-recursive dengan cara yang akan selalu menetapkan nilai yang tepat untuk $PS1[1-3]
sekaligus referensi diri. Untuk mendapatkan bagian ini Anda harus mempertimbangkan urutan ekspresi shell-matematika dievaluasi. Yang paling penting, shell-matematika selalu urutan terakhir dari bisnis untuk shell-matematika. Sebelum semua yang lain, shell memperluas nilai. Dengan cara ini Anda bisa mereferensikan nilai-lama untuk variabel-shell dalam ekspresi matematika setelah menetapkan dengan menggunakan $
.
Berikut ini contoh sederhana:
x=10; echo "$(((x+=5)+$x+x))" "$x"
40 15
Shell akan mengevaluasi pernyataan itu dengan terlebih dahulu mensubstitusi nilai di $x
mana pun $
referensi tanda dolar digunakan, dan dengan demikian ungkapan menjadi:
(x+=5)+10+x
... lalu shell menambahkan 5 ke nilai $x
dan kemudian memperluas seluruh ekspresi menjadi x+10+x
, sementara hanya mempertahankan nilai yang sebenarnya ditugaskan dalam variabel referensi. Dan nilai diperluas ekspresi matematika adalah 40, tetapi nilai akhir $x
adalah 15.
Itulah sebagian besar cara kerja $PS1
persamaan juga, kecuali bahwa ada tingkat lebih lanjut dari ekspansi / evaluasi matematika yang dieksploitasi dalam indeks array.
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
Saya tidak benar-benar yakin mengapa saya memilih untuk menggunakan di PS1[1]=!1
sana - saya kira itu mungkin hanya estetika konyol - tetapi ini memberikan 0 $PS1[1]
saat memperluas itu untuk substitusi parameter. Nilai bitwise AND untuk 0 dan yang lainnya akan selalu 0, tetapi tidak mengalami hubung pendek seperti yang &&
dilakukan boolean saat yang paling utama adalah 0 sehingga ekspresi kurung masih dievaluasi setiap waktu. Itu penting, tentu saja, karena elipsis pertama adalah tempat nilai awal $PS1[2,3]
ditetapkan.
Pokoknya, di $PS1[1]
sini dijamin 0 bahkan jika itu dirusak antara penarikan cepat. Di dalam kurung ada ...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
... $PS1[2]
ditugaskan perbedaan $PS1[3]
dan $SECONDS
, dan $PS1[3]
diberi hasil bagi dari nilai itu dan 3600. Semua nilai di sini diinisialisasi. Dan sebagainya:
${PS1[1]#${PS1[3]%%*??}0}
... jika ada setidaknya dua digit di dalam $PS1[3]
maka ekspansi batin ada nol, dan karena kita tahu $PS1[1]
0 maka jika $PS1[3]
bisa diganti dengan tidak ada, begitu juga apakah $PS1[1]
itu diperluas ke nilainya. Dengan cara ini hanya nilai satu digit untuk setiap iterasi $PS1[3]
penugasan akan memperluas nol di depan, dan $PS1[3]
itu sendiri diperluas modulo 60 segera setelah itu sementara secara bersamaan diberi nilai berikutnya yang lebih kecil berturut-turut untuk setiap jam, menit, detik.
Bilas dan ulangi, hingga iterasi terakhir saat $PS1[3]
ditimpa dengan nilai saat ini $SECONDS
sehingga dapat dibandingkan dengan $SECONDS
sekali lagi saat prompt diambil berikutnya.