Я запутался в следующем скрипте ( hello.go
).
//usr/bin/env go run $0 $@ ; exit
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
Это может выполнить. (на MacOS X 10.9.5)
$ chmod +x hello.go
$ ./hello.go
hello, world
Я не слышал о Шебанге, начиная с //
. И это все еще работает, когда я вставляю пустую строку в верхней части скрипта. Почему этот скрипт работает?
//&>/dev/null;x="${0%.*}";[ ! "$x" -ot "$0" ]||(rm -f "$x";cc -o "$x" "$0")&&exec "$x" "$@"
...
///....
вместо того,//...
чтобы быть наиболее совместимым!go run "$0" "$@"
Ответы:
Это не шебанг, это просто скрипт, запускаемый оболочкой по умолчанию. Оболочка выполняет первую строку
что вызывает
go
запуск с именем этого файла, поэтому в результате этот файл запускается как скрипт go, а затем оболочка завершает работу, не просматривая остальную часть файла.Но зачем начинать с
//
вместо просто/
или надлежащего притон#!
?Это потому, что файл должен быть действительным сценарием go, иначе go будет жаловаться. В go символы
//
обозначают комментарий, поэтому go видит первую строку как комментарий и не пытается ее интерпретировать. Символ,#
однако, не обозначает комментарий, поэтому обычный шебанг может привести к ошибке, когда go интерпретирует файл.Эта причина синтаксиса заключается в том, чтобы просто создать файл, который является одновременно сценарием оболочки и сценарием go, без единого шага на другом.
источник
/
как суффикс пути определяется как/.
; Когдаa
это не символическая ссылка,a
это то жеa/
самое, что иa/.
Тера, это случаи, когда путь может получить дополнительный/
без изменения значения. При выводе канонического пути есть шаг нормализации, заключающийся в последовательных слешах к единице. Конечно, это не чистая часть формального синтаксиса.///usr/bin/env go run $0 $@ ; exit
...Он запускается потому, что по умолчанию исполняемый файл считается скриптом / bin / sh. Т.е. если вы не указали какую-либо конкретную оболочку - это #! / Bin / sh.
// просто игнорируется в путях - вы можете считать, что это как '/'.
Таким образом, вы можете считать, что у вас есть скрипт оболочки с первой строкой:
Что делает эта строка? Он запускает 'env' с параметрами 'go run $ 0 $ @'. там 'go' - команда, а 'run $ 0 $ @' - аргументы и выход из скрипта впоследствии. $ 0 это имя скрипта. $ @ - это оригинальные аргументы скрипта. Таким образом, эта строка запускает Go, который запускает этот скрипт с его аргументами
Как отмечалось в комментариях, есть довольно интересные подробности о том, что две косые черты определяются реализацией, и этот сценарий станет POSIX-корректным, если он укажет три или более косых черт. Обратитесь к http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html за подробной информацией о том, как следует обрабатывать косые черты в путях.
Также обратите внимание, что в скрипте есть еще одна ошибка - $ @, вместо этого правильно использовать «$ @», потому что в противном случае, если какой-либо параметр содержит пробелы, он будет разделен на множество параметров. Например, вы не можете передать имя файла с пробелами, если вы не используете "$ @"
Этот конкретный сценарий, очевидно, опирается на идею, что «//» равно «/»
источник
Это будет работать для C ++ (и C, если этот C позволяет // для комментариев)
//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit
источник