Почему в этом случае я могу передавать аргументы в /usr/bin/env?

Почему в этом случае я могу передавать аргументы в /usr/bin/env?

Я читал вдругой ответчто я не могу передать интерпретатору аргументы, отличные от тех, которые я передаю /usr/bin/env:

Другая потенциальная проблема заключается в том, что этот #!/usr/bin/envтрюк не позволяет передавать аргументы интерпретатору (кроме имени скрипта, которое передается неявно).

Однако, похоже, мне это удаётся, потому что awkон ломается, когда я не устанавливаю флаг, -fи чинится, когда я устанавливаю флаг -f, при использовании /usr/bin/env:

Сначала без -fфлага:

$ cat wrap_in_quotes
#!/usr/bin/env awk
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
awk: syntax error at source line 1
 context is
     >>> . <<< /wrap_in_quotes
awk: bailing out at source line 1

Во-вторых, с -fфлагом:

$ vim wrap_in_quotes
$ cat wrap_in_quotes
#!/usr/bin/env awk -f
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
"foobar"
  • Итак, если согласносвязанный ответЯ не могу передать флаги интерпретатору. Почему я могу передать -fфлаг awk?

Я бегу macOS:

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.1
BuildVersion:   16B2657

решение1

Некоторые Unix-системы, в частности macOS (и до 2005 года FreeBSD), позволяют это делать, тогда как Linux — нет, но...

Если использовать envутилиту из недавнего выпуска пакета GNU coreutils (8.30+), то в ней есть нестандартная -Sопция, позволяющая указывать несколько аргументов в #!строках.

Обратный вопрос:Строка Shebang с `#!/usr/bin/env command --argument` не работает в Linux

решение2

Вы не можетепортативнопередавать интерпретатору несколько аргументов. В частности, Linux это не поддерживает.

Некоторые варианты Unix поддерживают более одного аргумента в строке shebang. Это касается современных систем macOS и некоторых других. СмотретьСтраница Свена Машека о переносимости оболочкидляСравнительная таблица вариантов Unixи много исторической информации.


Если вам нужен переносимый скрипт awk, то нет четкого решения. #!/usr/bin/envи #!/bin/shявляются единственными строками shebang, которые переносимы на практике: в зависимости от варианта Unix, awkмогут быть в /binили /usr/bin, или в некоторых других местах (например, /usr/xpg4/bin/awkв Solaris, чтобы получить POSIX — тот, что в /usr/binпредназначен для устаревших приложений). Поскольку #!/usr/bin/env awk -fне работает переносимо, остается #!/bin/sh. ( /bin/shможет быть устаревшей оболочкой Bourne, а не современной оболочкой POSIX, но любая платформа Unix имеет что-то там на практике.) Идея состоит в том, чтобы написатьполиглот, т. е. скрипт, который shинтерпретируется как инструкции для запуска awk, а awk интерпретирует его как желаемый скрипт. Это работает даже в системах, которые не распознают строки shebang, но по умолчанию используют shдля выполнения скрипта (некоторые старые unice или некоторые unix-подобные пользовательские пространства на не-Unix-ядрах).

#!/bin/sh
"exec" "awk" "-f" "$0" "$@" && 0 {}
… # awk script here

(Если вас беспокоит возможность переносимости на старые юниксы, см.Страница Свена Машекана "$@"поддержку и рассмотрите возможность использования ${1+"$@"}вместо этого.)

Связанный контент