Как использовать несколько аргументов для awk с shebang (т. е. #!)?
Я хотел бы выполнить поглазеть скрипт --re-interval С помощью shebang. "Наивный" подход
#!/usr/bin/gawk --re-interval -f
... awk script goes here
не работает, так как gawk вызывается с первым аргументом "--re-interval -f" (не рассыпается вокруг пробела), который он не понимает. Есть ли обходной путь для этого?
конечно, вы можете либо не вызывать gawk напрямую, но обернуть его в сценарий оболочки, который разбивает первый аргумент, или сделать сценарий оболочки, который затем вызывает gawk и put сценарий в другой файл, но мне было интересно, есть ли какой-то способ сделать это в одном файле.
поведение линий shebang отличается от системы к системе - по крайней мере, в программа он не разделяет аргументы пробелами. Я просто забочусь о том, как это сделать в системе, которая ведет себя так; сценарий не должен быть переносимым.
9 ответов:
это, кажется, работает для меня с (g)awk.
#!/bin/sh arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "" "$@" # The real awk program starts here { print }Примечание
#!работает/bin/sh, поэтому этот скрипт сначала интерпретируется как сценарий оболочки.сначала я просто пробовал
"exec" "/usr/bin/gawk" "--re-interval" "-f" "" "$@", но awk рассматривал это как команду и распечатывал каждую строку ввода безоговорочно. Вот почему я поставил вarbitrary_long_name==0- он должен все время терпеть неудачу. Вы можете заменить его какой-нибудь тарабарщиной. В принципе, я искал ложное условие в awk, которое не будет негативно влияет на сценарий оболочки.в shell-скрипт, тег
arbitrary_long_name==0определяет переменную с именемarbitrary_long_nameи устанавливает его равным=0.
линия shebang никогда не была указана как часть POSIX, SUS, LSB или любой другой спецификации. АФАИК, это даже не было должным образом задокументировано.
существует грубый консенсус о том, что он делает: возьмите все между
!и\nиexecего. Предполагается, что все между!и\n- это полный путь к интерпретатору. Нет единого мнения о том, что произойдет, если он содержит пробел.
- некоторые операционные системы просто рассматривать все это как путь. В конце концов, в большинстве операционных систем пробелы или тире являются законными в пути.
- некоторые операционные системы разделяются на пробелы и рассматривают первую часть как путь к интерпретатору, а остальные-как отдельные аргументы.
- некоторые операционные системы разделены на первый пробелы и лечить передняя часть как путь к интерпретатором и остальные как single аргумент (который является то, что вы видите).
- некоторые даже не поддерживают shebang линии на всех.
к счастью, 1. и 4. вроде бы вымерли, но 3. довольно распространена, поэтому вы просто не можете полагаться на возможность передать более одного аргумента.
и поскольку расположение команд также не указано в POSIX или SUS, вы обычно используете этот единственный аргумент, передавая исполняемый файл имя до
env, так что это можно определить местоположение исполняемого файла; например:#!/usr/bin/env gawk[очевидно, это еще предполагает определенный путь для
env, но есть только очень мало систем, где он живет в/bin, так что это вполне безопасно. Расположениеenvявляется гораздо более стандартизированным, чем расположениеgawkили еще хуже что-то вродеpythonилиrubyилиspidermonkey.]что означает, что вы не можете использовать любой аргументы на всех.
я столкнулся с той же проблемой, без видимого решения из-за того, как пробелы обрабатываются в shebang (по крайней мере, на Linux).
тем не менее, вы можете передать несколько вариантов в shebang, пока они короткие варианты и они могут быть сцепленные (путь GNU).
например, вы не можете иметь
#!/usr/bin/foo -i -fно вы можете иметь
#!/usr/bin/foo -ifочевидно, что это работает только тогда, когда параметры имеют короткие эквиваленты и не принимают никаких аргументов.
в Cygwin и Linux все После пути shebang анализируется в программе как один аргумент.
Это можно взломать вокруг этого с помощью другого
awkскрипт внутри shebang:#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}это будет выполняться
{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}в awk.
И это будет исполнять/usr/bin/gawk --re-interval -f path/to/your/script.awkв вашей системной оболочке.
#!/bin/sh ''':' exec YourProg -some_options "" "$@" '''вышеупомянутый трюк shebang shell является более портативным, чем
/usr/bin/env.
в руководстве gawk (http://www.gnu.org/manual/gawk/gawk.html), конец раздела 1.14 обратите внимание, что вы должны использовать только один аргумент при запуске gawk из линии shebang. В нем говорится, что ОС будет рассматривать все После пути к gawk как один аргумент. Возможно, есть другой способ указать ? Возможно, ваш скрипт может ссылаться на вашу оболочку в строке shebang, run
gawkкак команда, и включить текст вашего скрипта в качестве "здесь документа".
почему бы не использовать
bashиgawkсам, чтобы пропустить мимо shebang, прочитайте скрипт и передайте его как файл во второй экземплярgawk [--with-whatever-number-of-params-you-need]?#!/bin/bash gawk --re-interval -f <(gawk 'NR>3' ) exit { print "Program body goes here" print }(- то же самое, естественно, может быть выполнено, например, с
sedилиtail, но я думаю, что есть какая-то красота зависит только отbashи ;)
просто для удовольствия: есть следующее довольно странное решение, которое перенаправляет stdin и программу через файловые дескрипторы 3 и 4. Вы также можете создать временный файл для скрипта.
#!/bin/bash exec 3>&0 exec <<-EOF 4>&0 BEGIN {print "HALLO"} {print $1} EOF gawk --re-interval -f <(cat 0>&4) 0>&3одна вещь раздражает об этом: оболочка делает переменное расширение на скрипт, так что вы должны цитировать каждый $ (как это сделано во второй строке скрипта) и, вероятно, больше, чем это.
для портативного решения, использовать
awk, а неgawk, вызовите стандартную оболочку Борна (/bin/sh) С вашим shebang, и вызватьawkнепосредственно, передавая программу в командной строке как документ here, а не через stdin:#!/bin/sh gawk --re-interval <<<EOF PROGRAM HERE EOFПримечание: нет до
awk. Вот и выходитstdinдоступно дляawkдля чтения входных данных. Если у вас естьgawkустановлен и на вашемPATH, это достигает всего, что я думаю, что вы были пытаясь сделать с вашим оригинальным примером (предполагая, что вы хотите, чтобы содержимое файла было сценарием awk, а не входным сигналом, который, я думаю, ваш подход shebang рассматривал бы его как).
Comments