Что означает #!/Usr/bin/... в начале файла?

Я могу сделать что-то подобное в Haskell:

#!/usr/bin/runghc
main=putStrLn "Hello World"

Затем я могу запустить его с помощью ./hello.hs

Мой вопрос: почему первая строка игнорируется? Комментарии в haskell начинаются с --, но первая строка по-прежнему игнорируется. Он даже загружается в ghci. Трюк также работает с Python и Perl.

Но когда я делаю что-то подобное в Java:

#!/usr/local/jdk1.6.0_13/bin/javac
...

Javac дает мне ошибку компилятора.

Итак, как это работает и как я могу заставить его работать с Java?

Спасибо.

Ответы

Ответ 1

#! называется " shebang" и является способом выполнения сценариев Unix. Когда вы попросите ОС выполнить файл, выяснится, что это не обычный файл .exe, а #! в начале служит волшебным маркером, который инструктирует ОС выполнить команду после #! и подключите эту команду, чтобы этот файл стал аргументом этой команды

если myfile.py содержит

#!/usr/bin/python

выполнение этого файла не сильно отличается от запуска

$ /usr/bin/python myfile.py

Знания моего Хаскелла бедны. Но для вашего конкретного случая кажется, что команда runghc просто читает первую строку, анализирует любые аргументы, указанные на этом #! line, записывает остальную часть файла во временный файл и запускает ghc в этом временном файле (который будет иметь первое залоговое удержание - см. runghc.hs в источниках ghc для получения дополнительной информации.)

Если вы хотите сделать то же самое с javac, вы можете использовать тот же подход, что и runghc. Напишите оболочку, которая ест первую строку файла, записывает остальную часть файла в файл temp и запускает javac в этом файле.

Ответ 2

Если ваш файл hello.hs, а первая строка - "#!/usr/bin/runghc", то оболочка выполнит:

/usr/bin/runghc hello.hs

Эта первая строка в основном сообщает оболочке, что использовать для запуска script.

Что касается примера java, первой строкой должен быть исполняемый файл, который запускает script, а не компилирует script.

Ответ 3

Мой вопрос: почему первая строка игнорируется? Комментарии в haskell начинаются с - но первая строка по-прежнему кажется проигнорированной. Он даже загружается в ghci. Трюк также работает с Python и Perl.

"Трюк" работает в Python и Perl, потому что # запускает комментарий на этих языках, поэтому интерпретатор видит эту строку как комментарий и игнорирует ее. Поэтому для них это ничего особенного.

В Haskell # не запускается комментарий, поэтому он обычно не работает. Тем не менее, GHC (возможно, также и другие реализации, если память служит, объятия тоже сделали) имеет специальный случай для строк shebang. Если первая строка файла начинается с #!, это рассматривается как комментарий. Это отклонение от спецификации языка было введено точно, чтобы сделать

$ chmod +x hello.hs
$ ./hello.hs

работа. Он не работает с javac, потому что в него нет специального случая для строк shebang.

Ответ 4

Shebang работает только с интерпретируемыми языками.... это вообще ничего не значит для компилятора, который в большинстве случаев будет ошибочен

Ответ 5

Причина, по которой это работает, заключается в том, что Python, Perl и, по-видимому, Haskell, являются все интерпретируемыми языками. Это стандартный способ Unix для обозначения интерпретатора, который будет запускать script. Java - это скомпилированный язык и не может работать с интерпретатором.

Ответ 6

Javac - это компилятор, а не интерпретатор.

Не хватает интерактивного режима, который, я считаю, вызывает магию. То же самое не будет работать с GCC, поскольку в нем отсутствует такая же функция.

dmd (компилятор D), например, является примером компилятора, который поддерживает интерпертацию, имеет такое интерактивное редактирование (#!/usr/bin/dmd -run).

Ответ 7

Местоположение исполняемого файла на вашем компьютере интерпретирует ваш script. Java - это скомпилированный язык, поэтому ему не нужен такой оператор.

Кроме того, дело в том, что это специальный комментарий, конструкция на Java не была бы законной, так как # не является маркером комментариев. Если такая конструкция будет иметь смысл... что это не так... это будет выглядеть так:

//!/usr/local/jdk1.6.0_13/bin/javac