Что означает!# (Удар-фунт) в сценарии оболочки 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 я получаю следующую ошибку на консоли:

ошибка: файл скрипта не закрывает свой заголовок с!# или::!# обнаружена одна ошибка

Из приведенного выше сообщения об ошибке я понял следующее:

  1. !# закрывающий тег для заголовка exec scala "$0" "$@"что, вероятно, говорит Скала, что после !# это код Scala для выполнения.
  2. !# можно заменить на ::!#,

Основанный исключительно на экспериментах (я предполагаю, что это где-то описано):

Начиная с 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.

Другие вопросы по тегам