You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断GNU AWK脚本是否通过-i/@include引入?实现双模式运行

GNU AWK实现脚本/库双模式(类似Python name,支持嵌套引入)

要实现GNU AWK脚本同时作为独立工具和函数库使用(直接运行时执行BEGIN块,被@include/-i引入时跳过BEGIN块),可以利用FILENAME和ARGV数组判断当前脚本是否为主脚本,替代环境变量方案,完美支持嵌套引入。

核心思路

GNU AWK中,直接运行的主脚本文件名会出现在ARGV数组(命令行参数列表)中;而通过@include/-i引入的脚本,其文件名不会出现在ARGV里。我们可以通过对比当前脚本的FILENAME与ARGV中的元素,判断是否为主脚本,进而决定是否执行BEGIN块逻辑。

为了兼容相对路径、绝对路径的差异,使用GNU AWK 4.1+提供的realpath()函数统一路径格式;若版本较低,可改用basename对比(兼容性稍弱)。

实现示例

main.gawk

#!/bin/sh
exec gawk -f "$0" -- "$@"

@include "incl.gawk"

BEGIN {
    is_main = 0
    # 遍历命令行参数,检查当前脚本是否为主脚本
    for (i = 1; i < ARGC; i++) {
        if (realpath(FILENAME) == realpath(ARGV[i])) {
            is_main = 1
            break
        }
    }
    if (is_main) {
        do_included_stuff()
        exit do_main_stuff()
    }
}

function do_main_stuff() { print 1 }

incl.gawk

#!/bin/gawk -f

BEGIN {
    is_main = 0
    for (i = 1; i < ARGC; i++) {
        if (realpath(FILENAME) == realpath(ARGV[i])) {
            is_main = 1
            break
        }
    }
    if (is_main) {
        do_included_stuff()
    }
}

function do_included_stuff() { print 2 }

低版本GNU AWK兼容方案(<4.1)

如果无法使用realpath(),可以通过提取文件名的basename来对比:

function get_basename(path) {
    return gensub(/.*\//, "", 1, path)
}

# 在BEGIN块中替换为:
if (get_basename(FILENAME) == get_basename(ARGV[i])) {
    is_main = 1
    break
}

执行验证

$ ./main.gawk
2
1

$ ./incl.gawk
2

嵌套引入支持

如果incl.gawk再引入其他脚本(比如subincl.gawk),只需在subincl.gawk中复用相同的BEGIN判断逻辑即可,只有直接运行subincl.gawk时才会执行它的BEGIN块,完全支持多层嵌套。

内容的提问来源于stack exchange,提问作者taprs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 03:14:57