Nawk(New Awk)的发展与增强功能

Awk 最早在 1977 年Aho、Weinberger 和 Kernighan 开发,最初是为快速编写 "一行命令"(one-liners)短小的文本处理程序 而设计的。然而,Awk 受到了用户的广泛欢迎,一些人甚至将其作为主要编程工具,用于复杂任务。

最初的作者对 Awk 被用于大规模任务感到惊讶,但最终接受了这一事实,并决定改进 Awk,使其成为更强大的通用编程工具。在 1985 年,他们发布了 新版 Awk(Nawk, "New Awk"),以区别于原始版本。


1. Nawk 的主要增强功能

新版 Nawk 引入了多个重要改进,使其更适用于复杂任务:

1.1 用户自定义函数

  • 旧版 Awk 不支持函数,代码复用较困难。
  • Nawk 允许用户定义函数,使代码结构更加清晰。

示例:实现 signum(符号函数)

{ for (field=1; field<=NF; ++field) { print signum($field) } }

function signum(n) {
   if (n < 0)
       return -1
   else if (n == 0)
       return 0
   else
       return 1
}

说明

  • function signum否 {...} 定义了一个 signum 函数,用于返回数字 n 的符号:
    • 负数 返回 -1
    • 返回 0
    • 正数 返回 1
  • 所有参数都是局部变量,避免影响全局变量

1.2 getline 读取外部文件或管道

  • 旧版 Awk 只能处理命令行指定的输入文件
  • Nawk 允许使用 getline 动态读取文件或管道数据

用法

getline            # 从当前输入流读取一行到 `$0`
getline myvar      # 读取一行并存入变量 `myvar`
getline < "file"   # 从 `file` 读取一行到 `$0`
getline myvar < "file"  # 从 `file` 读取一行存入 `myvar`
"ls -l" | getline  # 运行命令 `ls -l` 并读取第一行输出到 `$0`

示例:从文件 data.txt 逐行读取

BEGIN {
    while (getline line < "data.txt") {
        print "Read:", line
    }
}

1.3 关闭文件 close()

  • close("file") 允许重新读取文件,而不必重新启动 Awk。
close("myfile")  # 关闭文件 "myfile",下次可以重新读取

1.4 运行 Shell 命令 system()

Nawk 提供 system("command") 来执行 Shell 命令。例如:

system("rm myfile")  # 删除文件 myfile
system("date")       # 显示当前日期

1.5 访问命令行参数 ARGCARGV

  • ARGC:命令行参数的个数。
  • ARGV数组,存储命令行参数。

示例

awk 'BEGIN { print "Total args:", ARGC; for (i=0; i<ARGC; i++) print i, ARGV[i] }' file1 file2

输出

Total args: 3
0 awk
1 file1
2 file2

1.6 三元运算符 ?:

  • 格式
    status = (condition == "green") ? "go" : "stop"
    
  • 等价于
    if (condition == "green") 
        status = "go"
    else 
        status = "stop"
    

1.7 新增数学函数

函数 描述
sin(x) 正弦,x 为弧度
cos(x) 余弦,x 为弧度
atan2(y,x) y/x 的反正切,范围 π
rand() 生成 0 <= number < 1 的随机数
srand(seed) 设置随机数种子

1.8 新增字符串函数

函数 描述
match(s, r) s 中查找正则 r,返回起始索引或 0
sub(r, t, s) 替换 s第一个 符合 r 的部分为 t
gsub(r, t, s) 替换 s所有 符合 r 的部分为 t

示例

BEGIN {
    str = "hello world hello"
    sub(/hello/, "hi", str)  # 替换第一个 "hello"
    print str  # 输出 "hi world hello"

    gsub(/hello/, "hi", str)  # 替换所有 "hello"
    print str  # 输出 "hi world hi"
}

1.9 多维数组支持

  • 旧版 Awk 只支持一维数组
  • Nawk 允许使用 array[row,col] 表示多维数组

示例:打印矩阵及其转置

BEGIN {
    count = 1
    for (row = 1; row <= 3; ++row) {
        for (col = 1; col <= 5; ++col) {
            printf("%4d", count)
            matrix[row, col] = count++
        }
        printf("\n")
    }

    printf("\nTransposed:\n")
    for (col = 1; col <= 5; ++col) {
        for (row = 1; row <= 3; ++row) {
            printf("%4d", matrix[row, col])
        }
        printf("\n")
    }
}

输出

   1   2   3   4   5
   6   7   8   9  10
  11  12  13  14  15

Transposed:
   1   6  11
   2   7  12
   3   8  13
   4   9  14
   5  10  15

1.10 删除数组元素 delete

delete array[key]
  • 示例
BEGIN {
    arr["apple"] = 5
    arr["banana"] = 3
    delete arr["apple"]
    print "apple count:", arr["apple"]  # 输出空值
}

2. 结论

增强功能 描述
用户自定义函数 支持 function name(args) {}
getline 读取外部文件 getline var < "file"
close() 关闭文件 close("file")
system() 运行 Shell 命令 system("ls")
ARGC/ARGV 访问参数 ARGV[i] 获取参数
三元运算符 ?: status = (cond) ? "yes" : "no"
新增数学函数 sin(x), cos(x), rand()
新增字符串函数 match(), sub(), gsub()
多维数组 array[row, col]
删除数组元素 delete array[key]

新版 Nawk 更加强大,适合更复杂的文本处理任务!🚀

最后修改: 2025年01月30日 星期四 01:36