Saat mendiskusikan perbedaan antara /usr/bin/time
shell dan bash (bash dan zsh) bawaan time
, seseorang menyebutkan bahwa seseorang dapat menggunakan \time
steno untuk mendapatkan /usr/bin/time
.
Pertama tampaknya seperti jalan pintas yang tidak bersalah, tetapi kemudian beberapa pertanyaan muncul:
- Kenapa juga
t\ime
bekerja? - Mengapa
\cd
mengubah direktori, meskipun/usr/bin/cd
¹ tidak?
Jadi jelas, \foo
tidak setara dengan $(which foo)
. Pertanyaannya sekarang:
Apakah perilaku yang diamati \foo
pada bash dan zsh dengan cara apa pun dicakup oleh definisi POSIX tentang shell, dan jika demikian, mengapa berperilaku seperti itu?
Catatan kaki 1: /usr/bin/cd
adalah, di sistem saya,
#!/bin/sh
builtin cd "$@"
shell
quoting
posix
time-utility
Jonas Schäfer
sumber
sumber
Jawaban:
t\ime
atau\cd
(atau"tim"e
atau'cd'
atau${-##*}time
atau${-+time}
dan setiap kombinasi lain dari mengutip dan ekspansi Anda bisa memikirkan yang akhirnya akan memutuskan untuktime
ataucd
), adalah bahwa: cara lain untuk menuliscd
dantime
.Namun, itu akhirnya akan menyelesaikan
cd
atautime
di kemudian hari parsing dan interpretasi sintaksis shell. Secara khusus, itu terjadi lama setelah pengenalan kata kunci shell dan penggantian alias terjadi.Jadi, pada saat shell adalah mencari kata kunci dalam bahasa, ia tidak mengakui
ti\me
sebagaitime
kata kunci shell. Jadi a:akan dikenali oleh shell sebagai perintah sederhana sebagai lawan dari
time
kata kunci diikuti oleh perintah sederhana.Maka tanda kutip
ti\me
akan diproses (di sini backslash mengutipm
karakter yang tidak perlu kutip, karakter kutip dihapus, Anda dapatkantime
) dantime
perintah akan dicari seperti perintah lain (dalam daftar builtin , fungsi dan file yang dapat dieksekusi$PATH
. Kemungkinan besar akan ada di/bin/time
sini)Sebab
cd
, tidak adacd
kata kunci dalam bahasa shell, hanyacd
perintah builtin (yang lebih diutamakan daripada Anda/usr/bin/cd
). Namun, jika Anda mendefinisikan alias untukcd
(sukaalias cd=pushd
), sama lagi. Sebagai pengganti alias dilakukan sangat awal, sebelum penghapusan kutipan, jika Anda memiliki alias untukcd
dan bukan untuk\cd
(perhatikan bahwa tidak banyak shell mengizinkan alias dengan backslash di dalamnya), kemudian dengan menulis:Anda memastikan
cd
alias Anda tidak diganti.Singkatnya, mengutip nama perintah atau bagian dari itu mencegah dari yang dilihat sebagai kata kunci shell (kata kunci menjadi hal-hal seperti
while
,for
,if
,{
...time
adalah kata kunci di beberapa kerang saja), dan melewati alias Anda mungkin memiliki untuk itu .Namun itu tidak memaksa perintah untuk menyelesaikan file yang dapat dieksekusi
$PATH
, perintah masih dicari pertama di antara fungsi (yang dapat Anda kerjakan dengan melakukancommand time cmd...
) dan builtins (yang dapat Anda kerjakan dengan melakukanenv time cmd...
, meskipun saya tidak tahu tentang sebuah shell yang memilikitime
perintah builtin ).Perhatikan bahwa mengutip juga dapat memiliki pengaruh pada perilaku builtin khusus dari
typeset
/declare
/export
/local
... keluarga di beberapa kerang. Lihat Apakah kutipan diperlukan untuk penugasan variabel lokal? untuk detail.sumber
time
dancd
yang mengarah ke perbedaan dalam perilaku yang diamati adalah bahwa itutime
adalah kata kunci dancd
merupakan perintah bawaan ?time
adalah kata kunci dancd
bukan itu. (dan jika Anda memiliki alias untukcd
atautime
, itu akan menjadi masalah lain). Yangcd
dibangun atau tidak tidak memiliki insiden pada titik ini (sejauh pengaruh kutipan berkaitan). Namun beberapa shell memiliki beberapa builtin yang berada di antara kata kunci dan builtin karena penguraiannya dilakukan secara berbeda dari builtin lainnya. Itu adalah kasusexport
/typeset
/declare
. Saya mungkin harus menambahkan beberapa catatan tentang hal ini dalam jawaban ini.