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

Awk脚本在Ubuntu报非法变量引用错误但在MinGW-64正常运行

Awk脚本跨环境运行报错问题

错误现象

在MinGW-64(GNU Awk 5.0.0)中正常运行的Awk脚本,在Ubuntu 22.04(mawk 1.3.4)执行时出现如下错误:

awk: /home/username/chuleta/chuleta/glst.awk: line 22: illegal reference to variable a

awk: /home/username/chuleta/chuleta/glst.awk: line 23: illegal reference to variable a

即使将shebang从#!/usr/bin/gawk -f改为#!/usr/bin/awk -f,问题依然存在。

脚本代码

#!/usr/bin/awk -f

# generates list of terms related to a topic

# this funcion substitutes a with b in $0
func change(a,b) {
    while (i=index($0,a))
            $0 = substr($0,1,i-1) b substr($0,i+length(a))
}

{
    # we delete the base folder (received in var RTO) from the input line
    # and clean it of other stuff
    change(RTO,"")
    change(".txt","")
    change("/"," ")
    change("_"," ")
    split($0,a," ")
    # using arr as associative array by using same string as index
    # this prevents duplicated strings and code is shorter
    # since we don't have to maintain a counter for index
    for (x in a)  # this is line 22
        arr[a[x]]=a[x] # this is line 23
}

END{
    n=asort(arr,sarr)
    for (x in sarr)
        printf("%s ",sarr[x])
}

补充信息

  • 示例输入数据集:
/home/username/chuleta/chuleta-data/java/8/chuleta_foreach_loop.txt
/home/username/chuleta/chuleta-data/java/8/chuleta_basic_functional_interfaces_in_function_package.txt
/home/username/chuleta/chuleta-data/java/8/chuleta_advantages_new_date_time_api.txt
/home/username/chuleta/chuleta-data/java/8/chuleta_new_date_time_api.txt
/home/username/chuleta/chuleta-data/java/8/chuleta_solve_interface_default_methods_conflict.txt
/home/username/chuleta/chuleta-data/java/8/chuleta_lambdas_with_parameters.txt
  • 脚本逻辑:传入RTO变量指定基础目录,移除路径、.txt后缀,将/和_替换为空格后分割为数组a,通过关联数组去重后排序输出。

问题原因

核心差异在于mawk和gawk对函数参数的作用域处理不同:

  • GNU Awk(gawk)默认将函数参数视为局部变量,函数内部的a和主程序中的数组a是两个独立的变量,互不干扰。
  • mawk中函数参数是全局变量,change函数的参数a和主程序里定义的数组a是同一个变量。当调用change函数时,参数a被赋值为字符串(比如RTO路径、.txt等),覆盖了后续split生成的数组a,导致遍历a时,它已经不是数组类型,触发“illegal reference to variable a”错误。

解决方法

修改change函数的参数名,避免和主程序中的数组a重名,比如将参数a改为old_str,b改为new_str:

修改后的脚本:

#!/usr/bin/awk -f

# generates list of terms related to a topic

# this funcion substitutes old_str with new_str in $0
func change(old_str, new_str) {
    while (i=index($0, old_str))
            $0 = substr($0,1,i-1) new_str substr($0,i+length(old_str))
}

{
    # we delete the base folder (received in var RTO) from the input line
    # and clean it of other stuff
    change(RTO,"")
    change(".txt","")
    change("/"," ")
    change("_"," ")
    split($0,a," ")
    # using arr as associative array by using same string as index
    # this prevents duplicated strings and code is shorter
    # since we don't have to maintain a counter for index
    for (x in a)
        arr[a[x]]=a[x]
}

END{
    n=asort(arr,sarr)
    for (x in sarr)
        printf("%s ",sarr[x])
}

修改后,mawk和gawk环境下都能正常运行,因为函数参数和主程序数组不再重名,避免了全局变量覆盖的问题。


内容的提问来源于stack exchange,提问作者Tulains Córdova

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 13:34:58