Skip to content

文本处理工具

概述

Linux 提供了一套强大的文本处理工具,包括 sed、awk 等。这些工具可以高效地处理和转换文本数据。

sed - 流编辑器

sed(Stream Editor)是一个强大的文本处理工具,可以对文本进行过滤和转换。

基本语法

bash
sed [选项] '命令' 文件
sed [选项] -e '命令1' -e '命令2' 文件
sed [选项] -f 脚本文件 文件

常用选项

选项说明
-n静默模式,不自动打印
-e添加命令
-f从文件读取命令
-i直接修改文件
-i.bak修改前备份
-r / -E使用扩展正则表达式

替换命令 s

bash
# 基本替换(每行第一个)
$ sed 's/old/new/' file.txt

# 全局替换
$ sed 's/old/new/g' file.txt

# 忽略大小写
$ sed 's/old/new/gi' file.txt

# 只替换第 N 个匹配
$ sed 's/old/new/2' file.txt

# 显示被替换的行
$ sed -n 's/old/new/p' file.txt

# 直接修改文件
$ sed -i 's/old/new/g' file.txt

# 备份后修改
$ sed -i.bak 's/old/new/g' file.txt

地址和范围

bash
# 指定行号
$ sed '3s/old/new/' file.txt       # 第 3 行
$ sed '1,5s/old/new/' file.txt     # 第 1-5 行
$ sed '3,$s/old/new/' file.txt     # 第 3 行到最后

# 匹配模式的行
$ sed '/pattern/s/old/new/' file.txt

# 范围模式
$ sed '/start/,/end/s/old/new/' file.txt

删除命令 d

bash
# 删除指定行
$ sed '3d' file.txt                # 删除第 3 行
$ sed '1,5d' file.txt              # 删除第 1-5 行
$ sed '$d' file.txt                # 删除最后一行

# 删除匹配的行
$ sed '/pattern/d' file.txt

# 删除空行
$ sed '/^$/d' file.txt

# 删除注释行
$ sed '/^#/d' file.txt

打印命令 p

bash
# 打印指定行
$ sed -n '3p' file.txt             # 打印第 3 行
$ sed -n '1,5p' file.txt           # 打印第 1-5 行
$ sed -n '$p' file.txt             # 打印最后一行

# 打印匹配的行
$ sed -n '/pattern/p' file.txt

# 打印行号
$ sed -n '=' file.txt

插入和追加

bash
# 在指定行前插入
$ sed '3i\新行内容' file.txt

# 在指定行后追加
$ sed '3a\新行内容' file.txt

# 在匹配行前后插入
$ sed '/pattern/i\插入内容' file.txt
$ sed '/pattern/a\追加内容' file.txt

替换整行 c

bash
# 替换指定行
$ sed '3c\新内容' file.txt

# 替换匹配的行
$ sed '/pattern/c\新内容' file.txt

多命令处理

bash
# 使用分号分隔
$ sed 's/a/A/g; s/b/B/g' file.txt

# 使用 -e 选项
$ sed -e 's/a/A/g' -e 's/b/B/g' file.txt

# 使用大括号分组
$ sed '/pattern/{s/old/new/; s/foo/bar/}' file.txt

高级技巧

bash
# 使用不同的分隔符
$ sed 's|/usr/local|/opt|g' file.txt
$ sed 's#http://#https://#g' file.txt

# 引用匹配内容
$ sed 's/\(.*\)/【\1】/' file.txt      # 添加括号
$ sed 's/[0-9]*/(&)/' file.txt         # & 代表匹配内容

# 转换大小写
$ sed 's/[a-z]/\u&/g' file.txt         # 首字母大写
$ sed 's/.*/\U&/' file.txt             # 全部大写
$ sed 's/.*/\L&/' file.txt             # 全部小写

实用示例

bash
# 删除 HTML 标签
$ sed 's/<[^>]*>//g' file.html

# 删除行首空白
$ sed 's/^[ \t]*//' file.txt

# 删除行尾空白
$ sed 's/[ \t]*$//' file.txt

# 添加行号
$ sed = file.txt | sed 'N;s/\n/\t/'

# 每行后添加空行
$ sed 'G' file.txt

# 合并连续空行为一个
$ sed '/^$/N;/^\n$/d' file.txt

awk - 模式处理语言

awk 是一种强大的文本处理语言,特别适合处理结构化数据。

基本语法

bash
awk 'pattern { action }' file
awk -F 分隔符 'pattern { action }' file

内置变量

变量说明
$0整行内容
$1, $2, ...第 N 个字段
NF字段数量
NR当前行号
FNR当前文件的行号
FS字段分隔符
OFS输出字段分隔符
RS记录分隔符
ORS输出记录分隔符
FILENAME当前文件名

基本操作

bash
# 打印所有行
$ awk '{print}' file.txt
$ awk '{print $0}' file.txt

# 打印指定字段
$ awk '{print $1}' file.txt
$ awk '{print $1, $3}' file.txt

# 指定分隔符
$ awk -F ':' '{print $1}' /etc/passwd
$ awk -F ',' '{print $1, $2}' file.csv

# 打印行号
$ awk '{print NR, $0}' file.txt

模式匹配

bash
# 匹配正则表达式
$ awk '/pattern/' file.txt
$ awk '/pattern/ {print $1}' file.txt

# 条件匹配
$ awk '$1 > 100' file.txt
$ awk '$1 == "value"' file.txt
$ awk 'NR > 5' file.txt

# 范围匹配
$ awk '/start/,/end/' file.txt

# 字段匹配
$ awk '$1 ~ /pattern/' file.txt
$ awk '$1 !~ /pattern/' file.txt

BEGIN 和 END

bash
# BEGIN 在处理前执行
$ awk 'BEGIN {print "开始处理"} {print}' file.txt

# END 在处理后执行
$ awk '{print} END {print "处理完成"}' file.txt

# 设置变量
$ awk 'BEGIN {FS=":"; OFS="\t"} {print $1, $3}' /etc/passwd

# 统计行数
$ awk 'END {print NR}' file.txt

算术运算

bash
# 基本运算
$ awk '{print $1 + $2}' file.txt
$ awk '{sum = $1 + $2; print sum}' file.txt

# 求和
$ awk '{sum += $1} END {print sum}' file.txt

# 平均值
$ awk '{sum += $1} END {print sum/NR}' file.txt

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

字符串函数

bash
# 长度
$ awk '{print length($1)}' file.txt

# 子串
$ awk '{print substr($1, 1, 3)}' file.txt

# 分割
$ awk '{split($1, arr, "-"); print arr[1]}' file.txt

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

# 大小写转换
$ awk '{print toupper($1)}' file.txt
$ awk '{print tolower($1)}' file.txt

# 查找
$ awk '{if (index($0, "pattern") > 0) print}' file.txt

控制结构

bash
# if-else
$ awk '{if ($1 > 100) print "大"; else print "小"}' file.txt

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

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

# 数组
$ awk '{count[$1]++} END {for (k in count) print k, count[k]}' file.txt

格式化输出

bash
# printf
$ awk '{printf "%-10s %5d\n", $1, $2}' file.txt

# 格式说明符
# %s  字符串
# %d  整数
# %f  浮点数
# %-  左对齐
# %10 宽度

实用示例

bash
# 统计词频
$ awk '{for(i=1;i<=NF;i++) count[$i]++} END {for(w in count) print count[w], w}' file.txt | sort -rn

# 计算文件大小总和
$ ls -l | awk '{sum += $5} END {print sum}'

# 处理 CSV
$ awk -F ',' '{print $1 "\t" $2}' file.csv

# 提取日志中的 IP
$ awk '{print $1}' access.log | sort | uniq -c | sort -rn

# 条件统计
$ awk '$3 > 1000 {count++} END {print count}' file.txt

# 合并行
$ awk 'ORS=NR%3?"\t":"\n"' file.txt

diff 和 patch

diff - 比较文件

bash
# 基本比较
$ diff file1.txt file2.txt

# 统一格式
$ diff -u file1.txt file2.txt

# 并排显示
$ diff -y file1.txt file2.txt

# 忽略空白
$ diff -w file1.txt file2.txt

# 递归比较目录
$ diff -r dir1/ dir2/

# 生成补丁
$ diff -u old.txt new.txt > changes.patch

patch - 应用补丁

bash
# 应用补丁
$ patch < changes.patch

# 指定文件
$ patch file.txt < changes.patch

# 反向应用(撤销)
$ patch -R < changes.patch

# 干运行
$ patch --dry-run < changes.patch

comm - 比较排序文件

bash
# 显示三列:只在文件1、只在文件2、两者共有
$ comm file1.txt file2.txt

# 只显示共有的行
$ comm -12 file1.txt file2.txt

# 只显示 file1 独有的行
$ comm -23 file1.txt file2.txt

join - 连接文件

bash
# 基于公共字段连接
$ join file1.txt file2.txt

# 指定连接字段
$ join -1 2 -2 1 file1.txt file2.txt

# 指定分隔符
$ join -t ':' file1.txt file2.txt

小结

本章介绍了 Linux 强大的文本处理工具:

  • sed:流编辑器,适合简单的文本替换和转换
  • awk:模式处理语言,适合结构化数据处理
  • diff/patch:文件比较和补丁
  • comm/join:文件合并和比较

掌握 sed 和 awk 将大大提高你的文本处理效率。


上一章:文本编辑器

下一章:正则表达式