Понимание проблемы:
Насколько я понимаю, у ОП есть сложный сценарий под названием script.awk
:
#!/usr/bin/awk -f
BEGIN{print "ARGC", ARGC; for(i=0;i<ARGC;++i) print "ARG"i,ARGV[i]}
, который ОП хотел бывызывать с использованием различных традиционных однобуквенных опций в стиле POSIX или длинных опций в стиле GNU.Опции POSIX начинаются с одного символа (-
), в то время как длинные опции начинаются с двух символов (--
).Это, однако, терпит неудачу, поскольку awk интерпретирует эти аргументы для передачи самому awk, а не списку аргументов сценариев.Например:
$ ./script.awk
ARGC 1
ARG0 awk
$ ./script.awk -arg
awk: not an option: -arg
Вопрос: Есть ли способ написания POSIX-совместимого скрипта, который может обрабатывать такие переносимые аргументы?(Предложения приведены в исходном вопросе.)
Наблюдение 1: Хотя это не сразу ясно, следует отметить, что сообщение об ошибке генерируется mawk и не более распространенная версия GNU gawk .В случае сбоя mawk gawk не делает:
$ mawk -f script.awk -arg
mawk: not an option -arg
$ gawk -f script.awk -arg
ARGC 2
ARG0 gawk
ARG1 -arg
Тем не менее, следует отметить, что как для gawk, так и для mawk можно наблюдать различное поведение, когда аргументы конфликтуют с необязательными аргументами awk.Пример:
$ mawk -f script.awk -var # this fails as gawk expects -v ar=foo
mawk: improper assignment: -v ar
$ gawk -f script.awk -var # this fails as gawk expects -v ar=foo
gawk: `oo' argument to `-v' not in `var=value' form
$ gawk -f script.awk -var=1 # this works and creates variable ar
$ mawk -f script.awk -var=1 # this works and creates variable ar
$ mawk -f script.awk -foo # this fails as it expects a file oo
mawk: cannot open oo (No such file or directory)
$ gawk -f script.awk -foo # this fails as it expects a file oo
gawk: fatal: can't open source file `oo' for reading (No such file or directory)
Наблюдение 2: ОП предлагает использовать двойной - , чтобы указать, что последовательные опции являются только частью awk.Это, однако, расширение как mawk, так и gawk, и не является частью стандарта POSIX .
--
: указывает на однозначный конецопции. источник: man mawk
--
: сигнализировать об окончании опций.Это полезно, чтобы разрешить дальнейшие аргументы самой программе AWK начинать с -
.Это обеспечивает согласованность с соглашением о разборе аргументов, используемым большинством других программ POSIX. источник: man gawk
Кроме того, использование двойного дефиса предполагает, что все аргументы после --
являются файлами:
$ ./script.awk -- -arg1 file
ARGC 3
ARG0 mawk
ARG1 -arg1
ARG2 file
mawk: cannot open -arg1 (No such file or directory)
Предложение 1: Хотя концепция флагов удобна, вы можете рассмотреть возможность использования стандартного POSIX-совместимого назначения в качестве аргументов:
$ ./script.awk arg1=1 arg2=1 arg3=1 file
Однако недостатком этого является то, что эти назначения обрабатываются только после выполнения блока BEGIN
.(ср. стандарт POSIX )
Предложение 2: простое улучшение заключается в использовании ARGV
и ARGC
и использовании аргументов без дефисов.Это немного более похоже на BSD (cfr ps aux
) и может выглядеть следующим образом:
$ ./script.awk arg1 arg2 arg3
ARGC 4
ARG0 gawk
ARG1 arg1
ARG2 arg2
ARG3 arg3
Предложение 3: Если ни один из вышеперечисленных вариантов не подходит вам,Вы должны рассмотреть возможность использования гибрида между sh
и awk
.Слово «гибрид» подразумевает, что мы пишем синтаксис, который распознается как sh
, так и awk
.Программа awk состоит из пар вида:
pattern { action }
, где pattern
можно игнорировать.Это очень похоже на синтаксис составной команды sh
:
{ compound-list ; }
Это позволяет нам теперь написать следующий скрипт оболочки script.sh
:
#!/bin/sh
{ "awk" "-f" "$0" "--" "${@}" ; "exit" ;}
# your awk script comes here
Написав его таким образом,awk
будет интерпретировать первое действие как не что иное, как объединение строк.sh
с другой стороны выполнит его номинально.
К сожалению, хотя это выглядит многообещающе, это НЕ работает из-за эффекта двойного дефиса.
$ ./script.sh file # this works
ARGC 2
ARG0 awk
ARG1 file
$ ./script.sh -arg file # this does not work
ARGC 3
ARG0 mawk
ARG1 -arg1
ARG2 file
mawk: cannot open -arg1 (No such file or directory)
Уродливое решение может заключаться в том, чтобы начать анализировать сам скрипт, чтобы удалить первые две строки, прежде чем передать его обратно в awk.Но это решит проблему только для сценариев, имеющих только блок BEGIN.