Что означает!# (Удар-фунт) в сценарии оболочки sh / Bash?
Я хочу понять, как работает этот скрипт Scala:
#!/usr/bin/env bash
exec scala "$0" "$@"
!#
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world! " + args.toList)
}
}
HelloWorld main args
В строке 3, что делает "!#"? Затем остаток файла подается на стандартный ввод программы Scala? Кроме того, '!#' Где-нибудь задокументировано?
NB: Самая близкая вещь, которую я смог найти, хотя это не имеет прямого отношения к делу, это вопрос переполнения стека. Почему вам нужно поместить #!/ Bin/bash в начале файла сценария? (о начале скрипта Bash).
3 ответа
Файлы сценариев могут иметь необязательный заголовок, который игнорируется, если присутствует. Есть два способа отформатировать заголовок: любой, начинающийся с #! и заканчивая! # или начинающийся с:: #! и заканчивая::! #.
Таким образом, следующий код является просто заголовком для скрипта Scala:
#!/usr/bin/env bash
exec scala "$0" "$@"
!#
Когда я удалил !#
в примере программы в ответе BluesRockAddict я получаю следующую ошибку на консоли:
ошибка: файл скрипта не закрывает свой заголовок с!# или::!# обнаружена одна ошибка
Из приведенного выше сообщения об ошибке я понял следующее:
!#
закрывающий тег для заголовкаexec scala "$0" "$@"
что, вероятно, говорит Скала, что после!#
это код Scala для выполнения.!#
можно заменить на::!#
,
Основанный исключительно на экспериментах (я предполагаю, что это где-то описано):
Начиная с Scala 2.10.0, нестандартный (из POSIX-сценариев POSIX) pound-bang (! #) Больше не требуется в среде оболочки POSIX. Работает следующая строка (но она должна быть первой строкой скрипта без пробелов):
#!/usr/bin/env scala
Однако единственный способ обеспечить шебанг в пакетном файле Windows - обмануть его, заставив Scala использовать себя в качестве первого аргумента. Следовательно, Scala необходимо знать, где находится последняя строка командного файла, и, следовательно, требуется закрывающая строка::!#. Вот рабочий пример:
::#!
call scala %0 %*
goto :eof
::!#
Исправление: у меня изначально был #!/ Usr/bin/env scalav (обратите внимание на завершающий v), который является моим скриптом для определения свойства "scala.script", добавив несколько библиотек в classpath перед самим exec scala. Таким образом, можно определить имя выполняемого скрипта, хотя скаляр должен быть в вашей переменной PATH.