Распространение скрипта: я должен использовать / bin / gawk или / usr / bin / gawk для shebang?

12

Gawk обычно находится в / bin или / usr / bin? Я бы пошел с, #!/usr/bin/env gawkно тогда я не могу использовать аргументы. Щас пользуюсь #!/bin/gawk -f. Скрипт очень длинный, содержит много одинарных кавычек и работает с stdin.

В руководстве по GNU Awk есть раздел 1.1.4 Исполняемые программы awk, в котором в его примере используется #! / Bin / awk, но далее говорится:

Обратите внимание, что во многих системах awkможно найти в /usr/binвместо /bin. Пусть покупатель будет бдителен.

Что делает большинство людей? Я читал, что sed предположительно стандартизирован в / bin, тогда как perl предположительно стандартизирован в / usr / bin (та же страница, что и в ссылке sed, но они не позволят мне сделать третью ссылку для этого поста). Как насчет awk / gawk? Кто-нибудь знает, что является более распространенным или популярным?

user2672807
источник
Почему вы используете -f? Не /bin/gawkдостаточно? Также это может быть актуально.
Terdon

Ответы:

7

Шебанг не должен был быть таким гибким . Могут быть случаи, когда работает второй параметр , я думаю, что FreeBSD - один из них.

gawk и большинство утилит, которые поставляются с ОС, как ожидается, будут в /usr/bin/.

В прежние времена UNIX было принято /usr/монтировать через NFS или какой-либо менее дорогой носитель, чтобы сэкономить место на локальном диске и затраты на рабочую станцию. /bin/должен был иметь все необходимое для загрузки в однопользовательском режиме . Поскольку /usr/он не был смонтирован на надежном носителе, в него было /bin/включено достаточно утилит, чтобы сделать его достаточно дружественным для общего администрирования и устранения неполадок.

Первоначально это было унаследовано в Linux, но, поскольку дисковое пространство больше не является проблемой и в большинстве случаев /usr/находится в корневой файловой системе, текущая тенденция состоит в том, чтобы переместить все в /usr/bin(по крайней мере, в мире Linux). Поэтому ожидается, что большинство утилит, установленных дистрибутивом, будут там. Даже самые основные утилиты, как cp, rm, и lsт.д. (ну, еще нет).

Относительно выбора Шебанга. Традиционно это то, что администраторы или пользователи должны редактировать в соответствии со своей средой. Насколько известно разработчику, в системах других людей интерпретатор может находиться где угодно в файловой системе (например /usr/local/bin, /opt/gawk-4.0.1/bin). Правильно упакованные сценарии (rpm, deb и т. Д.) Поставляются с зависимостью от пакета дистрибутива (т. Е. Интерпретатор имеет известное местоположение) или сценарием конфигурации, который устанавливает надлежащий hashbang во время установки.

forcefsck
источник
14

Если вам не нужно передавать аргументы в команду, то #!/usr/bin/env gawkэто путь, однако многие ядра (включая Linux) принимают только один аргумент для программ shebang.

В противном случае вы можете создать программу polyglot, которая является одновременно оболочкой оболочки и сценарием awk. Вот один для awk.

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here

Разбор оболочки:

  • true + /;- команда true(которая ничего не делает) с двумя инертными аргументами +и /.
  • Призыв к gawk. Это может быть любой фрагмент оболочки, который не содержит символов новой строки и где пишется косая черта \/(оболочка не возражает, кроме как внутри кавычек).
    Вызов использует execдля замены оболочки gawk вместо выполнения gawk в качестве подпроцесса.
  • exit;- выйти из корпуса, если не было обнаружено gawk. Все, что после этого игнорируется, за исключением того, что это должен быть допустимый синтаксис оболочки на случай, если оболочка попытается проанализировать всю строку перед началом ее выполнения.

Разбор Awk:

  • Бит между косыми чертами - это регулярное выражение.
  • true + /REGEX/- состояние. trueявляется неопределенной переменной, поэтому ее числовое значение равно 0, а не то, что это имеет значение.
  • {} - Если указанное условие выполняется, ничего не делать.
Жиль "ТАК - перестань быть злым"
источник
5

Предложенное Жилем решение действительно является очень хорошим подходом (наконец, имейте репутацию, чтобы голосовать на своем посту :)).

В любом случае, насколько я понимаю, execкоманда делает ее exitправой после ненужной, фактически недоступной, так как процесс оболочки заменяется на awk.

Кроме того, чтобы awkскрипт мог получить доступ к своим параметрам вызова, я бы предложил некоторые изменения в предлагаемом решении:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here

-a "$0"Позволяет сценарий , чтобы иметь доступ к его имени вызова, в противном случае он всегда будет получить awkили gawkпри обращении к ARGV[0]переменной. Точно так же, "$@"позволяет скрипту получить доступ к остальным параметрам в ARGV[1...N]массиве, а --предшествующее ему позволяет скрипту получать -<something>аргументы без их интерпретации gawk.

Одна вещь, которую следует запомнить / рассмотреть, это добавить exit(0);оператор в конец BEGIN { ... }блока программы- awkскрипта, иначе он awkбудет представлять угрозу для всех параметров, передаваемых в скрипт как входные файлы. (Обратите внимание, что это никак не связано с exitоператором, который мы удалили из true + ...строки, это был недостижимый оператор оболочки, в то время как этот предлагаемый выход находится в коде awk).

Marcelo
источник
Это exit(0)было очень полезно! Также, для пользователей macos, посмотрите эту суть: хороший портативный awk shebang найти нелегко.
Симус