在 AWK 中可移植地处理任意参数

Handling arbitrary arguments portably in AWK

我想让我的 shebang 启用 POSIX awk 程序有更多的标准接口 -- 不是使用 -v var=val 界面,但使用看起来像 Linux/UNIX 命令行中可用的其他程序的界面。我遇到的问题是 awk 脚本将标志传递给 awk —— 然后 awk 本身首先破解了这些标志。此外,awk 的不同实现具有不同的标志选项。最终结果是,几乎不可能构建一个 awk 程序,其接口只能解析 ARGC,ARGV[] 以获取标志。

所以,我最终将我的 awk 程序封装在 shell 中——这增加了我的支持和测试负担——以及 shell 代码如下所示:

arg_core=""
arg_directory=""
arg_module=""
arg_output=""
arg_regmap=""
arg_regpage=""
arg_help=0
arg_version=0
arg_verbose=0
while getopts c:d:m:o:p:r:hvV o
do
        case "$o" in
        c) arg_core="$OPTARG";;
        d) arg_directory="$OPTARG";;
        m) arg_module="$OPTARG";;
        o) arg_output="$OPTARG";;
        p) arg_regpage="$OPTARG";;
        r) arg_regmap="$OPTARG";;
        h) arg_help=1;;
        v) arg_version=1;;
        V) arg_verbose=1;;
        --) break;;
        ?) help >&2
             exit 1;;
        esac
done
shift `expr $OPTIND - 1`

# Handling help and version (verbose option also displays revision
# history and notes) is more easily done outside the getopts loop.
if [ $arg_version -gt 0 ]
then
        version
        [ $arg_verbose -gt 0 ] && rev_history
fi
if [ $arg_help -gt 0 ]
then
        [ $arg_version -gt 0 ] && echo
        help
fi
[ $arg_help -gt 0 -o $arg_version -gt 0 ] && exit 0

awk -v arg_core="$arg_core" -v arg_directory="$arg_directory" -v arg_module="$arg_module" -v arg_output="$arg_output" -v arg_regmap="$arg_regmap" -v arg_regpage="$arg_regpage" -f rffe2tpf.awk -- "$@"

我的问题是...我想消除 shell 脚本封装并想在 awk 中进行我的参数解析 -- 我想这样做便携。 (注意...我不是在问,"How do I do getopts in awk?",而是在问,"How do I from the shebang in an awk script portably stop awk from parsing flags?")有没有办法欺骗 awk 或 shebang 来实现这个目标?

发帖到 Whosebug 让我更深入地思考这个问题,我相信我有更接近解决方案的东西。如果有人 "shebang-foo" 我不知道可以解决这个问题,那么我会选择我自己的答案。

特别感谢 BinaryZebra 指点我 getopt.awk -- 因为我不再需要考虑滚动我的自己的 getopt() 实现。

我们可能无法从 shebang 中可移植地提供我们想要的行为,但我们能够显着限制 shell 脚本中的代码量以支持我们想要的行为。建议的解决方案是通用的,可用于我们所有的 awk 脚本。

我调用以下脚本bawk:

#! /usr/bin/env sh
p=
shift
awk -f "$p" -- "$@"

如果bawk放在我们的路径中,就可以在awk脚本的shebang中使用。这是一个测试脚本:

#! /usr/bin/env bawk
BEGIN { for (i=1; i<ARGC; i++) print ARGV[i] }

输出:

$ ./foo.awk -abc -1 -2 -3
-abc
-1
-2
-3