awk命令

awk 命令 #

awk是一个强大的文本处理语言,专为处理结构化文本数据而设计。它可以按行处理文本,将每行分割为字段,然后对这些字段执行操作。awk名称来源于其创建者的姓氏首字母:Aho、Weinberger 和 Kernighan。

语法 #

awk [选项] '程序' 文件...

awk [选项] -f 程序文件 文件...

常用选项 #

选项 描述
-F fs 指定字段分隔符(默认为空格)
-v var=value 设置变量
-f file 从文件中读取 awk 程序
-W 设置兼容性或警告级别

awk 程序结构 #

BEGIN { 初始化操作 }
/模式/ { 对匹配模式的行执行的操作 }
END { 最终操作 }

所有部分都是可选的。

内置变量 #

变量 描述
$0 当前记录(整行)
$1, $2, ... 当前记录的第 1、2、…个字段
NF 当前记录的字段数
NR 当前记录的行号
FNR 当前文件中的行号
FS 输入字段分隔符(默认为空格)
RS 输入记录分隔符(默认为换行符)
OFS 输出字段分隔符(默认为空格)
ORS 输出记录分隔符(默认为换行符)
FILENAME 当前输入文件名
ARGC 命令行参数数量
ARGV 命令行参数数组

常见用法 #

1. 打印整行 #

# 打印文件的所有行
awk '{print}' file.txt

# 等同于
awk '{print $0}' file.txt

2. 打印特定字段 #

# 打印每行的第1个字段
awk '{print $1}' file.txt

# 打印每行的第1和第3个字段
awk '{print $1, $3}' file.txt

# 自定义输出格式
awk '{print "First: " $1 ", Third: " $3}' file.txt

3. 使用自定义分隔符 #

# 使用冒号作为分隔符(适用于/etc/passwd文件)
awk -F: '{print $1}' /etc/passwd

# 使用多个字符作为分隔符
awk -F'[,:]' '{print $1, $2}' file.txt

4. 条件处理 #

# 只打印第3个字段大于100的行
awk '$3 > 100 {print $0}' file.txt

# 只打印包含"pattern"的行
awk '/pattern/ {print $0}' file.txt

# 组合条件
awk '$3 > 100 && /pattern/ {print $0}' file.txt

5. 使用 BEGIN 和 END 块 #

# 添加标题和总结
awk 'BEGIN {print "Report:"} {print $0} END {print "End of report."}' file.txt

# 计算总和
awk 'BEGIN {sum=0} {sum+=$1} END {print "Sum:", sum}' file.txt

6. 内置函数 #

# 转换为大写
awk '{print toupper($0)}' file.txt

# 计算长度
awk '{print length($0)}' file.txt

# 使用substr提取子字符串
awk '{print substr($1, 1, 3)}' file.txt

7. 格式化输出 #

# 格式化数字
awk '{printf "%.2f\n", $1}' file.txt

# 创建表格式输出
awk '{printf "%-10s %5d\n", $1, $2}' file.txt

8. 计算和统计 #

# 计算第1列的总和
awk '{sum += $1} END {print sum}' file.txt

# 计算第1列的平均值
awk '{sum += $1; count++} END {print sum/count}' file.txt

# 找出最大值
awk 'BEGIN {max = 0} $1 > max {max = $1} END {print max}' file.txt

9. 处理多个文件 #

# 处理多个文件,显示文件名
awk '{print FILENAME, $0}' file1.txt file2.txt

# 只处理特定文件中的行
awk 'FILENAME == "file1.txt" {print $0}' file1.txt file2.txt

10. 使用变量 #

# 在命令行设置变量
awk -v threshold=100 '$1 > threshold {print $0}' file.txt

# 在程序中设置变量
awk 'BEGIN {threshold = 100} $1 > threshold {print $0}' file.txt

11. 使用数组 #

# 计算每个单词的出现次数
awk '{for(i=1;i<=NF;i++) count[$i]++} END {for(word in count) print word, count[word]}' file.txt

# 使用多维数组
awk '{data[$1][$2]++} END {for(i in data) for(j in data[i]) print i, j, data[i][j]}' file.txt

12. 控制流 #

# 使用if-else
awk '{if ($1 > 100) print "High"; else if ($1 > 50) print "Medium"; else print "Low"}' file.txt

# 使用循环
awk '{for(i=1;i<=NF;i++) print $i}' file.txt

实用示例 #

1. 分析日志文件 #

# 统计HTTP状态码
awk '{print $9}' access.log | sort | uniq -c | sort -nr

2. 处理 CSV 文件 #

# 处理CSV文件,打印特定列
awk -F, '{print $1, $3}' data.csv

3. 计算文件中的数字总和 #

awk '{for(i=1;i<=NF;i++) sum+=$i} END {print sum}' numbers.txt

4. 提取特定列并排序 #

awk '{print $3}' file.txt | sort -n

5. 删除重复行(类似于 uniq) #

awk '!seen[$0]++' file.txt

6. 计算文件的行数、字数和字符数(类似于 wc) #

awk 'BEGIN {lines=0; words=0; chars=0} {lines++; words+=NF; chars+=length($0)+1} END {print lines, words, chars}' file.txt

7. 替换文本(类似于 sed) #

awk '{gsub(/old/, "new"); print}' file.txt

内置函数 #

函数 描述
length(str) 返回字符串长度
substr(str, start, len) 返回子字符串
toupper(str) 转换为大写
tolower(str) 转换为小写
index(str, substr) 返回子字符串的位置
match(str, regex) 正则表达式匹配
split(str, arr, sep) 分割字符串到数组
gsub(regex, repl, str) 全局替换
sub(regex, repl, str) 替换第一次匹配
sprintf(fmt, expr) 格式化字符串
rand() 返回 0 到 1 之间的随机数
int(num) 取整

提示 #

  • awk 是按行处理文本的,默认以空格或制表符作为字段分隔符
  • 使用单引号包围 awk 程序可以防止 shell 解释特殊字符
  • 使用-F选项可以指定自定义的字段分隔符
  • 在 awk 中,变量不需要声明就可以使用
  • awk 支持关联数组(类似于哈希表或字典)
  • 使用next语句可以跳过当前记录的处理
  • 使用exit语句可以提前结束程序
  • awk 支持正则表达式模式匹配
  • 对于复杂的 awk 程序,可以将其保存在文件中,然后使用-f选项执行
  • awk 是图灵完备的语言,可以用来编写复杂的程序