Biasanya, $0
dalam sebuah skrip diatur ke nama skrip, atau untuk apa pun itu dipanggil sebagai (termasuk path). Namun, jika saya gunakan bash
dengan -c
opsi, $0
disetel ke argumen pertama yang diberikan setelah string perintah:
bash -c 'echo $0 ' foo bar
# foo
Efeknya, sepertinya parameter posisi telah digeser, tetapi termasuk $0
. Namun shift
dalam string perintah tidak mempengaruhi $0
(seperti biasa):
bash -c 'echo $0; shift; echo $0 ' foo bar
# foo
# foo
Mengapa perilaku yang tampaknya aneh ini untuk string perintah? Perhatikan bahwa saya mencari alasan, alasannya, di balik penerapan perilaku aneh tersebut.
Orang bisa berspekulasi bahwa string perintah seperti itu tidak akan membutuhkan $0
parameter seperti yang biasanya didefinisikan, jadi untuk ekonomi juga digunakan untuk argumen normal. Namun, dalam hal itu perilaku shift
aneh. Kemungkinan lain adalah yang $0
digunakan untuk mendefinisikan perilaku program (ala bash
disebut sebagai sh
atau vim
disebut sebagai vi
), tetapi itu tidak bisa, karena di $0
sini hanya terlihat dalam string perintah dan bukan oleh program yang dipanggil di dalamnya. Saya tidak bisa memikirkan kegunaan lain untuk apa $0
, jadi saya bingung menjelaskan hal ini.
-
untuk$0
argumen sebagai idiom, seperti dish -c 'foo $1 $2' - a b
. Dengan cara ini terlihat cukup normal (setelah Anda mengetahui apa-
artinya itu)echo 'echo the other side of this pipe globs "$@"' | sh -s -- *
, meskipun, sayangnya,$0
umumnya bukan parameter yang-s
dapat diatur dengan opsi tream ... Ini dapat digunakan dalam banyak cara yang sama padaxargs
umumnya. Dan lainnya selain itu.--
, maka itu bisa saja memiliki interpretasi biasa 'dari sini mulai argumen', terlihat di beberapa program lain. Kemudian lagi, itu bisa membingungkan mereka yang tidak terbiasa-c
untuk berpikir--
sebenarnya memiliki interpretasi itu.Jawaban:
Itu memberi Anda kesempatan untuk menetapkan / memilih
$0
saat menggunakan skrip inline. Kalau tidak,$0
akan begitu sajabash
.Maka Anda bisa melakukannya misalnya:
Tidak semua kerang digunakan untuk melakukan itu. Shell Bourne melakukannya. Shell Korn (dan Almquist) memilih parameter pertama yang dituju
$1
. POSIX akhirnya menggunakan cara Bourne, jadiksh
danash
turunannya dikembalikan ke sana nanti (lebih lanjut tentang itu di http://www.in-ulm.de/~mascheck/various/find/#shell ). Itu berarti bahwa untuk waktu yang lama untuksh
(yang tergantung pada sistem didasarkan pada Bourne, Almquist atau Korn shell), Anda tidak tahu apakah argumen pertama masuk$0
atau$1
, jadi untuk portabilitas, Anda harus melakukan hal-hal seperti:Atau:
Untungnya, POSIX telah menentukan perilaku baru di mana argumen pertama masuk
$0
, jadi kita sekarang bisa melakukan:sumber
bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt
pada Ubuntu 14.04, bashversion 4.3.11(1)-release
, dan aku:txt files are *.txt
. Ootxt
file di direktori saat ini). Lihat jugabash -c 'echo "${1?}"' foo
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt
adalah inventif fantastis!SHELL -c 'shift $1; command' 2 1 arg1 arg2 ...
haha ...Perilaku ini didefinisikan oleh POSIX :
Adapun mengapa Anda menginginkan perilaku itu: ini memperlancar jarak antara skrip dan
-c
string. Anda dapat langsung mengkonversi antara keduanya tanpa perubahan perilaku. Daerah lain mengandalkan ini identik.Ini juga sejalan dengan cara kerja argumen program secara umum: ini pada akhirnya bermuara pada memanggil salah satu
exec
fungsi, di mana argumen pertama yang disediakan juga$0
, dan sama-sama umum argumen itu sama dengan executable yang Anda jalankan. Namun, kadang-kadang, Anda menginginkan nilai khusus di sana, dan tidak ada cara lain untuk mendapatkannya. Mengingat bahwa ada argumen, itu harus memetakan ke sesuatu, dan pengguna harus dapat mengatur apa itu.Konsistensi ini (dan kemungkinan kecelakaan historis) mengarah pada situasi yang Anda temukan.
sumber
argv[0]
.$0
hanya diatur ke yangargv[0]
diteruskan keexecve()
saat sukash
ataubash
. Untuk skrip,$0
disetel ke jalur yang diberikan sebagai argumen 1, 2 ... ke interpreter (dan untuk skrip yang dieksekusi secara langsung, yang berasal dari argumen jalur pertama yang dieksekusi ()).