Saya bingung tentang mengikuti skrip ( hello.go
).
//usr/bin/env go run $0 $@ ; exit
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
Itu bisa mengeksekusi. (pada MacOS X 10.9.5)
$ chmod +x hello.go
$ ./hello.go
hello, world
Saya belum pernah mendengar tentang shebang dimulai dengan //
. Dan masih berfungsi ketika saya memasukkan baris kosong di bagian atas skrip. Mengapa skrip ini berfungsi?
//&>/dev/null;x="${0%.*}";[ ! "$x" -ot "$0" ]||(rm -f "$x";cc -o "$x" "$0")&&exec "$x" "$@"
...
///....
alih-alih//...
menjadi yang paling kompatibel!go run "$0" "$@"
Jawaban:
Ini bukan shebang, itu hanya skrip yang dijalankan oleh shell default. Shell mengeksekusi baris pertama
yang menyebabkan
go
dipanggil dengan nama file ini, sehingga hasilnya adalah file ini dijalankan sebagai skrip go dan kemudian shell keluar tanpa melihat sisa file.Tetapi mengapa mulai dengan
//
bukan hanya/
atau shebang yang tepat#!
?Ini karena file tersebut harus skrip go yang valid, atau go akan mengeluh. Dalam go, karakter
//
menunjukkan komentar, jadi go melihat baris pertama sebagai komentar dan tidak berusaha menafsirkannya.#
Namun karakternya , tidak menunjukkan komentar, jadi shebang yang normal akan menghasilkan kesalahan ketika pergi menafsirkan file.Alasan sintaks ini adalah hanya untuk membangun file yang merupakan skrip shell dan skrip go tanpa ada yang menginjak yang lain.
sumber
/
sebagai akhiran path didefinisikan sebagai/.
; Ketikaa
bukan symlink,a
adalah sama dengana/
yang sama dengana/.
Thera adalah kasus di mana jalan bisa mendapatkan tambahan/
tanpa perubahan makna. Ketika mendapatkan jalur kanonik, ada langkah normalisasi yang mengontrak garis miring berurutan. Memang, itu bukan bagian yang bersih dari sintaks formal.///usr/bin/env go run $0 $@ ; exit
...Ini berjalan karena secara default file executable diasumsikan sebagai skrip / bin / sh. Yaitu jika Anda tidak menentukan shell tertentu - itu adalah #! / Bin / sh.
// hanya diabaikan di jalur - Anda dapat menganggapnya sebagai '/' tunggal.
Jadi Anda dapat mempertimbangkan bahwa Anda memiliki skrip shell dengan baris pertama:
Apa yang dilakukan garis ini? Ini berjalan 'env' dengan paramenters 'go run $ 0 $ @'. ada 'go' adalah perintah dan 'jalankan $ 0 $ @' adalah argumen dan keluar dari skrip setelahnya. $ 0 adalah nama skrip ini. $ @ adalah argumen skrip asli. Jadi baris ini berjalan pergi yang menjalankan skrip ini dengan argumennya
Ada detail yang cukup menarik, seperti yang ditunjukkan dalam komentar, bahwa dua garis miring didefinisikan implementasi, dan skrip ini akan menjadi POSIX-benar jika menetapkan tiga garis miring atau lebih. Rujuk ke http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html untuk perincian tentang cara penanganan garis miring di jalur.
Perhatikan juga bahwa ada kesalahan lain dalam skrip $ @ itu benar untuk menggunakan "$ @" sebagai gantinya, karena jika tidak ada parameter yang mengandung spasi maka akan dipecah menjadi banyak parameter. Misalnya Anda tidak dapat memasukkan nama file dengan spasi jika Anda tidak menggunakan "$ @"
Skrip khusus ini jelas bergantung pada gagasan bahwa '//' sama dengan '/'
sumber
Ini akan berfungsi untuk C ++ (dan C jika itu memungkinkan // untuk komentar)
//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit
sumber