Вызов скрипта с awk shebang с параметрами (vars)

У меня есть awk-скрипт, который я определил следующим образом:

#!/usr/bin/env awk
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }

Я сохранил его как columns и chmod +x сделал. Я хочу вызвать его так, чтобы start и end определялись при обходе файла. Я думал, что это должно работать:

cat some_file | columns -v start=2

Но это не так. Помощь!


person Ollie Saunders    schedule 13.09.2009    source источник


Ответы (4)


Попробуйте использовать:

#!/usr/bin/awk -f

в качестве переводчика

person agsamek    schedule 13.09.2009
comment
+1 за самое переносимое решение, так как оно использует только один аргумент. Несмотря на то, что путь к awk жестко запрограммирован (по необходимости, из-за необходимости обходиться одним аргументом), это должно работать на всех современных платформах Unix. (Сообщите, если вы знаете что-то, чего нет.) - person mklement0; 14.10.2014
comment
@ mklement0 На моем (NixOS) этого нет. Поскольку NixOS сохраняет все пакеты изолированными и нестандартными путями. Я думаю, что в моем случае лучше использовать ответ mss. EDIT Это тоже не работает, так как -S не совместим с POSIX :( - person Pallav Agarwal; 31.01.2016
comment
@PallavAgarwal: полезно знать, чем отличается NixOS. Обратите внимание, что пока ваша ОС может обрабатывать несколько токенов в строке shebang, все в порядке; другими словами: #!/usr/bin/env awk -f может работать на вас (например, работает в OS X, но не в Linux). - person mklement0; 31.01.2016
comment
@ mklement0 Если бы это сработало, я бы никогда не столкнулся с этим вопросом. И в любом случае весь смысл попыток найти правильный шебанг заключался в том, чтобы сделать скрипт, который работает везде. Если бы мне пришлось, я мог бы написать #!/nix/store/‹полный путь к исполняемому файлу awk› -f - person Pallav Agarwal; 01.02.2016
comment
@PallavAgarwal: Понятно. Мы можем сделать вывод, что не существует переносимого решения, работающего на всех платформах (за исключением создания исполняемого файла-оболочки). - person mklement0; 01.02.2016

env — самый простой способ справиться с этой проблемой:

#!/usr/bin/env -S awk -f

чтобы добавить дополнительные параметры и обеспечить отсутствие помех для ваших аргументов и аргументов awk:

#!/usr/bin/env -S awk -F: -f ${_} --
BEGIN {
    # delete argv[1], which == ENVIRON[_]
    delete ARGV[1]
} # rest of my awk program

поскольку env имеет стандарт POSIX, этот shbang должен помочь вам обойти трудности нестандартных реализаций shbang в unixen.

ИЗМЕНИТЬ

после написания этого я понял, что '-S' не является POSIX-совместимым расширением env для FreeBSD. Так что оболочка оболочки, вероятно, путь, как это ни прискорбно.

person mss    schedule 08.08.2011
comment
Мы хотим добавить это в GNU coreutils после версии 8.29. - person pixelbeat; 26.04.2018

К сожалению, это непросто решить портативным способом. Стандартная техника выглядит так (замените /usr/bin/awk на путь awk):

#!/usr/bin/awk -f

BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }

Жестко запрограммированный путь awk и нестандартный флаг -f делают его не переносимым на все *nix. Если вы собираетесь запускать свой скрипт только на одной машине, это может сработать. Однако, чтобы сделать переносимый скрипт awk, вам нужно будет обернуть его в скрипт оболочки. Вот два способа сделать это в одном файле:

Первый способ стандартный и легко читаемый:

#!/bin/sh

awk '
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }
' "$@"

К сожалению, это не удается по двум ключевым причинам:

  1. Если ваш awk-скрипт содержит символ ', вам нужно будет ввести его следующим образом: '"'"', чтобы «экранировать» его.
  2. Если вы используете текстовый редактор с подсветкой синтаксиса, вы не сможете правильно выделить свой awk-скрипт.

Другое решение — использовать sed для удаления оболочки sh:

#!/bin/sh
exec awk "$(sed '1,2d' "$0")" "$@"

BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }

Это что-то вроде двухстрочного заголовка шабанга. Он вызывает awk, используя файл из строки 3 ниже в качестве аргумента скрипта. Это позволяет вам сохранить вашу красивую подсветку синтаксиса, и вы по-прежнему можете использовать ' символов в свое удовольствие. Я вижу два минуса:

  1. Возможно, это не интуитивно понятно для чтения.
  2. Если вы используете линтер кода, это может не понравиться.
person Sudo Bash    schedule 13.12.2019

Ниже приведен ответ на эту проблему -

#!/bin/awk -f 
person VIPIN KUMAR    schedule 05.10.2016
comment
Хотя это хорошо работает для gawk, у него есть проблемы с debian/ubuntu, поскольку они используют mawk для /usr/bin/awk, которые не поддерживают параметр -f. - person Oliver Gondža; 21.08.2019