变量类型与初始化(Types and Initialization)

在 Awk 中,既支持用户自定义变量,也有内置变量。变量名必须以字母开头,由字母、数字或下划线(_)组成,并且不能与 Awk 保留字 冲突。此外,变量名不能包含空格

提示

  • 如果 Awk 程序遇到奇怪的错误,尝试更换变量名,可能是由于使用了保留字导致的。

1. 变量初始化

Awk 不需要声明变量,也无法声明变量。但在复杂程序中,建议在 BEGIN 代码块中显式初始化变量,以提高可读性并避免逻辑错误。例如:

BEGIN {
    total = 0
    count = 0
}

默认值

  • 未初始化的变量 在数值运算时默认为 0,在字符串操作时默认为 ""(空字符串)。
  • 依赖默认值可能会引发错误,建议显式初始化

2. 弱类型(Weak Typing)

Awk 没有数据类型,变量可以存储字符串数值,并根据操作自动转换:

var = 1776       # 作为数值
var = "1776"     # 作为字符串(但在数值计算中仍然有效)

两者在数值计算时等价

print var + 1

输出

1777

但是,如果 var 赋值为一个非数字字符串

var = "somestring"
  • 字符串操作正常:
    print var " is a string"
    
    输出
    somestring is a string
    
  • 数值计算时,Awk 会把它当作 0
    print var + 10
    
    输出
    10
    

错误示例

var = somestring  # 变量 somestring 未定义
  • 这会创建一个新变量 somestring,它的值默认为 0,导致错误。

3. 变量未初始化时的行为

  • 比较 var == 0 可以检测变量是否未初始化
    if (var == 0) print "var is uninitialized"
    
  • 打印未初始化变量时,不会输出 0,而是空行
    print something
    
    输出
    (空行)
    
    但是如果先显式赋值
    something = 0
    print something
    
    输出
    0
    

4. 数组与字符串

  • Awk 字符串变量 不是 字符数组,但可以使用 substr() 访问字符串中的字符:
    BEGIN {
        str = "Hello"
        print substr(str, 1, 2)   # 输出 "He"
    }
    
  • 数组将在后续章节介绍

Awk 内置变量

变量 说明
$1, $2, ... 字段变量(输入行的列)
$0 完整的一行
NR 当前处理的行号(从 1 开始)
NF 当前行的字段数
FILENAME 当前文件名
FS 输入字段分隔符(默认是空格)
RS 输入记录分隔符(默认是换行符)
OFS 输出字段分隔符(默认是空格)
ORS 输出记录分隔符(默认是换行符)
OFMT 数字格式化(默认 "%.6g"
ARGC 命令行参数数量
ARGV 命令行参数数组

5. 变量修改

字段变量 $1, $2 等是可修改的

$2 = "NewText"
  • 这将修改当前行的第二列,但不会影响输入文件
  • 通过 print $0,可以打印修改后的行:
    awk '{$2="Modified"; print $0}' input.txt
    
    示例输入 input.txt
    A B C
    X Y Z
    
    输出
    A Modified C
    X Modified Z
    

6. 变量修改与内置变量

可以修改 FSOFSRS 以改变 Awk 行、字段的处理方式

6.1 修改 FS(字段分隔符)

假设 data.txt 文件内容:

name:age:city
Alice:25:NY
Bob:30:LA

使用 FS=":": 作为字段分隔符

awk 'BEGIN { FS=":" } { print $1, $3 }' data.txt

输出

name city
Alice NY
Bob LA

6.2 修改 OFS(输出字段分隔符)

awk 'BEGIN { OFS=" - " } { print $1, $2, $3 }' data.txt

输出

name - age - city
Alice - 25 - NY
Bob - 30 - LA

6.3 修改 RS(输入记录分隔符)

默认 RS="\n"(换行符),如果文件是多行记录,可以改为 RS="" 处理空行分隔的数据

awk 'BEGIN { RS="" } { print "Record:", $0 }' address_book.txt

6.4 修改 ORS(输出记录分隔符)

awk 'BEGIN { ORS="\n---\n" } { print $0 }' data.txt

输出

name:age:city
---
Alice:25:NY
---
Bob:30:LA
---

7. 练习

  1. 地址簿格式化

    • 处理多行记录,每个地址用空行分隔:
    awk 'BEGIN { FS="\n"; RS="" } { print $1, $2, $3 }' address_book.txt
    
    • 示例 address_book.txt
      John Doe
      123 Main St
      New York, NY
      
      Alice Smith
      456 Oak St
      Los Angeles, CA
      
    • 输出
      John Doe 123 Main St New York, NY
      Alice Smith 456 Oak St Los Angeles, CA
      
  2. 格式化数值列表

    • 读取特殊分隔符开头的数字列表,并以该分隔符重新格式化:
    awk '{ OFS=$1; print $2, $3, $4, $5, $6 }' numbers.txt
    
    • 示例输入 numbers.txt
      , 10 20 30 40 50
      - 1 2 3 4 5
      
    • 输出
      10,20,30,40,50
      1-2-3-4-5
      

结论

  • Awk 变量是弱类型的,可以存储字符串数值
  • 未初始化的变量默认为 0""
  • 可修改内置变量FS, OFS, RS, ORS)来改变输入/输出格式
  • 字段 $1, $2, ... 可修改,但不会影响原始文件。

在下一章,我们将学习 Awk 的强大关联数组(Associative Arrays)! 🚀

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