一、内置函数详解
1. 数值函数
# 常用数值函数
awk 'BEGIN {
print sqrt(16) # 平方根:4
print int(3.7) # 取整:3
print rand() # 随机数:0-1之间
print srand() # 设置随机种子
print log(10) # 自然对数
print exp(2) # e的2次方
}'
2. 字符串函数
# 字符串处理函数
awk 'BEGIN {
str = "Hello World"
# 长度
print length(str) # 11
# 子串
print substr(str, 1, 5) # Hello
print substr(str, 7) # World
# 查找
print index(str, "World") # 7 (位置)
print match(str, /W[a-z]+/) # 7 (正则匹配位置)
# 替换
print sub(/World/, "AWK", str) # 替换第一个匹配项
print gsub(/l/, "L", str) # 替换所有匹配项
# 分割
split("a,b,c", arr, ",")
for(i in arr) print arr[i] # a b c
}'
3. 时间函数
# 时间相关函数
awk 'BEGIN {
print systime() # 当前时间戳
print strftime("%Y-%m-%d") # 格式化当前时间
print strftime("%H:%M:%S", systime()) # 指定时间戳格式化
}'
4. 其他实用函数
# 系统函数
awk 'BEGIN {
print system("echo Hello") # 执行系统命令
print getline # 从输入读取下一行
}'
二、自定义函数
1. 基本语法
function 函数名(参数列表) {
函数体
return 返回值
}
2. 实际示例
# 计算平均值函数
awk '
function avg(arr, n) {
sum = 0
for(i = 1; i <= n; i++) {
sum += arr[i]
}
return sum / n
}
{
scores[NR] = $2
}
END {
print "平均分:", avg(scores, NR)
}' students.txt
# 字符串处理函数
awk '
function format_name(first, last) {
return toupper(substr(first,1,1)) substr(first,2) " " toupper(last)
}
{
print format_name($1, $2)
}' names.txt
三、正则表达式进阶
1. 正则表达式操作符
# 基本正则
awk '/^[0-9]+$/ {print "纯数字:", $0}' file.txt # 行首到行尾都是数字
awk '/\.[a-zA-Z]{3,4}$/ {print "文件:", $0}' file.txt # 匹配文件扩展名
# 正则替换
awk '{gsub(/[0-9]+/, "NUM"); print}' file.txt # 替换所有数字为NUM
awk '{sub(/^.*@/, ""); print}' emails.txt # 去掉邮箱前缀
2. match函数的高级用法
# 提取匹配内容
awk '{
if(match($0, /[0-9]{4}-[0-9]{2}-[0-9]{2}/)) {
date = substr($0, RSTART, RLENGTH)
print "找到日期:", date
}
}' logs.txt
# 使用捕获组(GNU awk)
awk '{
if(match($0, /([0-9]{4})-([0-9]{2})-([0-9]{2})/, arr)) {
print "年:", arr[1], "月:", arr[2], "日:", arr[3]
}
}' logs.txt
四、多维数组处理
1. 模拟多维数组
# 使用分隔符模拟二维数组
awk '{
matrix[NR,1] = $1
matrix[NR,2] = $2
matrix[NR,3] = $3
}
END {
for(row = 1; row <= NR; row++) {
for(col = 1; col <= 3; col++) {
printf "%s\t", matrix[row,col]
}
print ""
}
}' data.txt
2. 关联数组的复杂应用
# 统计每个用户在不同日期的操作次数
awk '{
user = $1
date = $2
count[user "," date]++
}
END {
for(key in count) {
split(key, parts, ",")
print parts[1], parts[2], count[key]
}
}' user_log.txt
五、getline的高级用法
1. 从文件读取
# 读取配置文件
awk '
BEGIN {
while((getline line < "config.txt") > 0) {
if(line ~ /=/) {
split(line, kv, "=")
config[kv[1]] = kv[2]
}
}
close("config.txt")
}
{
print $1, config["prefix"] $2
}' data.txt
2. 从管道读取
# 执行命令并读取输出
awk '
BEGIN {
cmd = "ls -l"
while((cmd | getline) > 0) {
if(NF > 8) files[$NF] = $5 # 文件名和大小
}
close(cmd)
}
{
if($1 in files) {
print $1, files[$1]
}
}' file_list.txt
六、输入输出控制
1. 输出重定向
# 输出到不同文件
awk '{
if($2 >= 60) {
print $0 > "pass.txt"
} else {
print $0 > "fail.txt"
}
}
END {
close("pass.txt")
close("fail.txt")
}' scores.txt
2. 格式化输出控制
# 控制输出格式
awk 'BEGIN {
OFS = "\t" # 输出字段分隔符
ORS = "\n---\n" # 输出记录分隔符
}
{
print $1, $2, $3
}' data.txt
# printf的高级用法
awk '{
printf "%-10s %8.2f %5d\n", $1, $2, $3
}' sales.txt
七、错误处理与调试
1. 错误检查
# 检查getline返回值
awk '{
if((getline line) <= 0) {
print "读取失败或文件结束" > "/dev/stderr"
exit 1
}
print line
}'
2. 调试技巧
# 使用print调试
awk '{
print "DEBUG: processing line", NR, "with", NF, "fields" > "/dev/stderr"
# 实际处理逻辑
}' data.txt
# 使用dump变量
awk -d 'BEGIN {var=1; print var}' # 会输出变量信息到文件
八、性能优化技巧
1. 避免重复计算
# 不好的做法
awk '{
if(length($1) > 10) { # 每次都计算长度
print $1
}
}'
# 好的做法
awk '{
len = length($1) # 只计算一次
if(len > 10) {
print $1
}
}'
2. 合理使用正则
# 避免复杂正则
awk '$0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/'
# 简化为字符串比较(如果可能)
awk 'substr($0,1,19) ~ /^[0-9 :-]+$/'
九、实用中级示例
1. 日志分析脚本
#!/usr/bin/awk -f
# 分析Apache访问日志
BEGIN {
FS = " "
print "IP地址\t\t访问次数\t流量总计"
}
{
ip = $1
bytes = ($10 == "-" ? 0 : $10)
count[ip]++
total_bytes[ip] += bytes
}
END {
for(ip in count) {
printf "%-15s\t%8d\t%10d\n", ip, count[ip], total_bytes[ip]
}
}
2. 数据透视表
# 生成销售数据透视表
awk '
BEGIN {
FS = ","
print "产品\t一月\t二月\t三月\t总计"
}
NR > 1 {
product = $1
month = $2
sales = $3
monthly[product,month] += sales
total[product] += sales
}
END {
months["一月"] = "一月"; months["二月"] = "二月"; months["三月"] = "三月"
for(product in total) {
printf "%s", product
for(month in months) {
printf "\t%d", monthly[product,month]
}
printf "\t%d\n", total[product]
}
}' sales.csv
3. 配置文件解析器
# 解析INI格式配置文件
awk '
BEGIN { section = "global" }
/^\[.*\]$/ {
sub(/^\[/, "");
sub(/\]$/, "");
section = $0;
next
}
/^[a-zA-Z]/ && /=/ {
split($0, kv, "=");
config[section "/" kv[1]] = kv[2]
}
END {
for(key in config) {
print key " = " config[key]
}
}' config.ini
十、GNU AWK 扩展功能
1. 高精度计算
# 使用 -M 选项进行高精度计算
awk -M 'BEGIN {
print 1/3 # 精确到小数点后多位
print 2^100 # 大数计算
}'
2. 包含文件
# functions.awk
function square(x) { return x * x }
function cube(x) { return x * x * x }
# main.awk
@include "functions.awk"
BEGIN {
print square(5) # 25
print cube(3) # 27
}
3. 扩展库使用
# 使用JSON库(如果安装)
awk -l json 'BEGIN {
# JSON处理功能
}'
这些中级内容涵盖了 AWK 的核心中高级功能,掌握后可以处理更复杂的文本处理任务。