sed & awk 命令速查表
sed(流编辑器)和 awk(文本分析工具)是 Linux/Unix 文本处理的两大神器。sed 擅长基于模式的行操作和替换,awk 擅长结构化文本的字段分析和报表生成。本速查表覆盖了日常开发运维中最常用的 sed 和 awk 命令,从基础操作到高级技巧,每个命令都有实际使用示例。
快速参考
| 你要做什么 | 用哪个命令 |
| 查找替换文件中的文本 | sed -i 's/旧文本/新文本/g' 文件 |
| 打印文件第 5-10 行 | sed -n '5,10p' 文件 |
| 剔除空行和注释行 | sed '/^#/d;/^$/d' 文件 |
| 打印 CSV 的第一和第三列 | awk -F',' '{print \$1,\$3}' 文件 |
| 统计某列数值总和 | awk '{sum+=\$1} END {print sum}' 文件 |
| 过滤某列大于 100 的行 | awk '\$NF > 100' 文件 |
| 格式化输出表格 | awk '{printf "%-20s %5d\\n", \$1, \$NF}' |
sed 基础操作
``bash
# 文本替换
sed 's/pattern/replacement/' file # 替换每行第一个匹配
sed 's/pattern/replacement/g' file # 全局替换(所有匹配)
sed 's/pattern/replacement/2' file # 只替换每行第二个匹配
sed -i 's/pattern/replacement/g' file # 原地修改文件(GNU sed)
sed -i '' 's/pattern/replacement/g' file # 原地修改(macOS BSD sed)
sed -i.bak 's/pattern/replacement/g' file # 备份后替换(跨平台兼容)
# 行操作 sed -n '5,10p' file # 打印第 5 到 10 行 sed -n '/pattern/p' file # 打印匹配 pattern 的行 sed '5d' file # 删除第 5 行 sed '/pattern/d' file # 删除匹配行 sed '$d' file # 删除最后一行 sed -n '1~2p' file # 打印奇数行(从第1行起每2行) sed '2~2d' file # 删除偶数行
# 行内编辑
sed '3a\\new line' file # 在第3行后追加一行
sed '2i\\new line' file # 在第2行前插入一行
sed '5c\\replaced line' file # 将第5行替换为新行
sed '/pattern/r insert.txt' file # 在匹配行后插入文件内容
sed '/pattern/w output.txt' file # 将匹配行写入新文件
`
sed 高级操作
`bash
# 范围选择与复合操作
sed -n '/start/,/end/p' file # 打印两个模式之间的行
sed '/start/,/end/d' file # 删除范围之间的行
sed -n '5,/pattern/p' file # 从第5行到匹配行
sed '0,/pattern/{s/old/new/}' file # 只替换首次匹配
sed '/pattern/!d' file # 删除不匹配的行(保留匹配行)
# 多命令组合 sed '/pattern/{s/foo/bar/;s/baz/qux/}' file # 匹配行上执行多个替换 sed -e 's/foo/bar/' -e 's/baz/qux/' file # 执行多条替换命令 sed 's/foo/bar/g; s/baz/qux/g' file # 用分号分隔多条命令(GNU sed)
# 变换与转换 sed 's/.*/\\U&/' file # 整行转大写 sed 's/.*/\\L&/' file # 整行转小写 sed 's/\\b./\\U&/g' file # 每行首字母大写 sed 'y/abc/ABC/' file # 字符映射(a→A, b→B, c→C)
# 使用保持空间
sed -n 'h;n;G;p' file # 将偶数行合并到奇数行
sed '1!G;h;$!d' file # 倒序输出文件(tac 模拟)
`
sed 正则与模式
`bash
# 基本正则 (BRE)
sed '/^$/d' file # 删除空行(^ 行首, $ 行尾)
sed '/^#/d' file # 删除以 # 开头的注释行
sed '/^[[:space:]]*$/d' file # 删除纯空白行
sed '/foo.*bar/d' file # 删除包含 foo 后跟 bar 的行
sed 's/\\[.*\\]//g' file # 删除方括号及其内容
sed 's/^[[:space:]]*//' file # 删除行首空白
sed 's/[[:space:]]*$//' file # 删除行尾空白
# 扩展正则 (ERE) - 使用 -E 选项 sed -E 's/([0-9]+)/[\\1]/g' file # 将数字用方括号包裹 sed -E 's/^([^,]+),([^,]+)/\\2,\\1/' file # 交换第1和第2字段(CSV) sed -E '/^(#|$)/d' file # 删除注释行和空行 sed -E 's/[[:space:]]+/ /g' file # 合并连续空格为单个空格 sed -E 's/http://([^/]+).*/URL: \\1/' file # 提取 URL 域名
# 分组与反向引用
sed -E 's/([a-z]+)@([a-z]+)/\\1 AT \\2/g' file # 邮箱格式转换
sed -E 's/(.)(.)/\\2\\1/g' file # 交换相邻字符
sed -E 's/^(.{50}).*/\\1.../' file # 截断长行取前50字符
`
awk 基础操作
`bash
# 字段打印
awk '{print $1}' file # 打印第一个字段(默认空格分隔)
awk '{print $0}' file # 打印整行
awk '{print $1, $3}' file # 打印第 1 和第 3 字段
awk '{print NR, $0}' file # 带行号打印
awk '{print NF, $0}' file # 显示每行字段数
# 自定义分隔符 awk -F',' '{print $1, $3}' file # 逗号分隔(CSV 处理) awk -F: '{print $1, $6}' /etc/passwd # 冒号分隔 awk -F'[ ,;]' '{print $1, $2}' file # 多个分隔符 awk 'BEGIN {FS=":"} {print $1}' file # 在 BEGIN 块设置分隔符 awk -F'\t' '{print $2}' file # Tab 分隔
# 模式匹配 awk '/pattern/ {print}' file # 打印匹配行 awk '/^error/ {print NR, $0}' file # 打印以 error 开头的行及行号 awk '!/pattern/ {print}' file # 打印不匹配的行 awk 'NR > 1 {print}' file # 跳过标题行 awk 'NR % 2 == 0 {print}' file # 打印偶数行
# 条件过滤
awk '$3 > 100 {print}' file # 第 3 列大于 100
awk '$1 == "OK" {print}' file # 第 1 列等于 OK
awk 'length($0) > 80 {print}' file # 打印超过 80 字符的行
awk '$NF ~ /error/ {print}' file # 最后一列包含 error
awk '$1 >= 10 && $1 <= 100' file # 值在 10 到 100 之间
`
awk 高级操作
`bash
# 统计与聚合
awk '{sum+=$1} END {print "总和:", sum}' file # 求和
awk '{sum+=$1; count++} END {print "平均:", sum/count}' file # 平均
awk '{if ($1 > max) max=$1} END {print "最大值:", max}' file # 最大值
awk '{min=$1; if ($1 < min) min=$1} END {print "最小值:", min}' file # 最小值(简化版见 awk 字段处理)
# BEGIN / END 块 awk 'BEGIN {print "报告开始"} {print $0} END {print "共", NR, "行"}' file awk 'BEGIN {FS=":"; OFS="--"} {print $1, $3}' /etc/passwd awk 'BEGIN {printf "%-20s %10s\\n", "名称", "数值"; print "------------------------"} {printf "%-20s %10d\\n", $1, $2}' file
# 数组与计数 awk '{a[$1]++} END {for (k in a) print k, a[k]}' file # 计数各值出现次数 awk '{a[$1]+=$2} END {for (k in a) print k, a[k]}' file # 按第一列分组求和 awk '!seen[$0]++' file # 去重(保留首次出现)
# 多文件处理 awk 'FNR==NR {a[$1]; next} $1 in a' file1 file2 # 两文件求交集(按字段) awk 'FNR==NR {a[$1]=$2; next} {print $1, a[$1]}' map.txt data.txt # 基于键值映射替换 awk 'NR==FNR {a[$1]++; next} !a[$1]' all.txt exclude.txt # 排除文件中列出的项
# Shell 变量与外部命令 awk -v threshold=100 '$1 > threshold {print}' file # 传递 shell 变量 awk -v name="$USER" '{print name, $0}' file # 传递环境变量 awk '{"date" | getline now; print now, $0}' file # 执行外部命令 awk '{system("ls -l " $1)}' file # 对每行执行系统命令
# 字符串函数
awk '{print toupper($0)}' file # 转大写
awk '{print tolower($0)}' file # 转小写
awk '{print substr($1, 1, 3)}' file # 取子串(前3字符)
awk '{print length($0), $0}' file # 显示每行长度
awk '{gsub(/old/, "new"); print}' file # 行内全局替换
`
awk 字段处理
`bash
# 字段选择与重组
awk '{print $1, $(NF-1)}' file # 打印第一列和倒数第二列
awk '{print $NF}' file # 打印最后一列
awk '{$1=""; print $0}' file # 删除第一列
awk '{$NF=""; $1=""; print $0}' file # 删除第一列和最后一列
awk -v n=3 '{print $n}' file # 按变量动态选择列
# 格式化输出 awk '{printf "%-20s %5d %8.2f\\n", $1, $2, $3}' file # 格式化表格 awk 'BEGIN{OFS="|"} {print $1, $2, $3}' file # 设置输出分隔符为 | awk '{print $1 "," $2 "," $3}' file # 手动拼接 CSV awk -v OFS='\t' '{print $1, $2}' file # Tab 分隔输出
# 字段条件 awk '{if ($NF > 100) print}' file # 最后列大于 100 awk '$1 ~ /^[A-Z]/ {print}' file # 第一列以大写字母开头 awk '{max=($1>$2)?$1:$2; print max}' file # 取两列中的较大值 awk 'NR==1{min=$1} {if ($1 < min) min=$1} END {print "最小值:", min}' file # 最小值
# 高级字段解析 awk 'BEGIN {FPAT="[^,]*|\\"[^\\"]*\\""} {print $1}' file # 处理带引号的 CSV awk -F'[ ]+' '{print $1, $(NF-1)}' file # 不定长空格分隔 awk '{$1=$1; print}' file # 重新格式化(清理多余空白) ``
sed 基础(7)
| 命令 | 难度 | ||
|---|---|---|---|
sed 's/pattern/replacement/' file替换每行第一个匹配的文本 | 基础 | sed 's/foo/bar/' file.txt | |
sed 's/pattern/replacement/g' file全局替换所有匹配的文本 | 基础 | sed 's/foo/bar/g' file.txt | |
sed -i 's/pattern/replacement/g' file原地修改文件(替换文本) | 基础 | sed -i.bak 's/oldtext/newtext/g' config.ini | |
sed -n '5,10p' file打印第 5 到第 10 行 | 基础 | sed -n '10,20p' /var/log/syslog | |
sed '/pattern/d' file删除包含指定模式的行 | 基础 | sed '/^$/d' file.txt | |
sed '5d' file删除指定行号的行 | 基础 | sed '10d' file.txt | |
sed -n '/pattern/p' file只打印匹配模式的行 | 基础 | sed -n '/ERROR/p' /var/log/app.log |
sed 高级(6)
| 命令 | 难度 | ||
|---|---|---|---|
sed -n '/start/,/end/p' file打印两个模式之间的所有行 | 中级 | sed -n '/BEGIN/,/END/p' document.txt | |
sed 's/.*/\U&/' file将整行文本转换为大写 | 中级 | sed 's/.*/\U&/' file.txt | |
sed -n '1~2p' file打印奇数行(步进模式) | 中级 | sed -n '0~2p' file.txt | |
sed '/pattern/{s/foo/bar/;s/baz/qux/}' file在匹配行上执行多条替换命令 | 中级 | sed '/user/{s/name/id/;s/email/mail/}' config.txt | |
sed '1!G;h;$!d' file倒序输出文件(使用保持空间) | 高级 | sed '1!G;h;$!d' file.txt | |
sed 'y/abc/ABC/' file字符映射转换 | 中级 | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' file.txt |
sed 正则与模式(5)
| 命令 | 难度 | ||
|---|---|---|---|
sed -E 's/([0-9]+)/[\1]/g' file使用扩展正则和分组替换,用方括号包裹所有数字 | 中级 | sed -E 's/([0-9]+\.[0-9]+)/[\1]/g' data.txt | |
sed -E '/^(#|$)/d' file删除注释行和空行 | 中级 | sed -E '/^(#|$)/d' config.conf | |
sed -E 's/[[:space:]]+/ /g' file合并连续空白字符为单个空格 | 中级 | sed -E 's/[[:space:]]+/ /g' file.txt | |
sed -E 's/^([^,]+),([^,]+)/\2,\1/' file交换 CSV 中前两个字段 | 中级 | sed -E 's/^([^,]+),([^,]+)/\2,\1/' data.csv | |
sed 's/^[[:space:]]*//; s/[[:space:]]*$//' file同时删除行首和行尾空白 | 基础 | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' file.txt |
awk 基础(7)
| 命令 | 难度 | ||
|---|---|---|---|
awk '{print $1}' file打印第一个字段(默认空格分隔) | 基础 | awk '{print $1}' access.log | |
awk '{print NR, $0}' file带行号打印每一行 | 基础 | awk '{print NR, $0}' file.txt | |
awk -F',' '{print $1, $3}' file指定逗号分隔符,打印第 1 和第 3 字段 | 基础 | awk -F',' '{print $1, $3}' data.csv | |
awk '/pattern/ {print}' file打印匹配模式的行 | 基础 | awk '/ERROR/ {print}' /var/log/app.log | |
awk 'NR > 1 {print}' file跳过文件的第一行(标题行) | 基础 | awk 'NR > 1 {print}' data.csv | |
awk '$3 > 100 {print}' file打印第三列大于 100 的行 | 基础 | awk '$3 > 100 {print}' report.txt | |
awk 'length($0) > 80 {print}' file打印超过 80 个字符的行 | 基础 | awk 'length($0) > 80 {print}' source.py |
awk 高级(6)
| 命令 | 难度 | ||
|---|---|---|---|
awk '{sum+=$1} END {print sum}' file计算第一列数值的总和 | 中级 | awk '{sum+=$1} END {print "Total:", sum}' sales.txt | |
awk '{a[$1]++} END {for (k in a) print k, a[k]}' file统计第一列各值的出现次数 | 中级 | awk '{a[$1]++} END {for (k in a) print k, a[k]}' ip.log | |
awk '!seen[$0]++' file去除重复行(保留首次出现) | 中级 | awk '!seen[$0]++' file.txt | |
awk 'FNR==NR {a[$1]; next} $1 in a' file1 file2两文件按字段求交集 | 高级 | awk 'FNR==NR {a[$1]; next} $1 in a' keys.txt data.txt | |
awk -v threshold=100 '$1 > threshold {print}' file将 shell 变量传递到 awk 脚本 | 中级 | awk -v limit=500 '$1 > limit {print}' data.txt | |
awk '{gsub(/old/, "new"); print}' file在 awk 中使用行内全局替换 | 中级 | awk '{gsub(/[0-9]+/, "NUM"); print}' data.txt |
awk 字段处理(7)
| 命令 | 难度 | ||
|---|---|---|---|
awk '{print $NF}' file打印每行的最后一个字段 | 基础 | awk '{print $NF}' /etc/passwd | |
awk '{print $1, $(NF-1)}' file打印第一列和倒数第二列 | 中级 | awk '{print $1, $(NF-1)}' data.txt | |
awk '{$1=""; print $0}' file删除第一列(将其置空) | 中级 | awk '{$1=""; print $0}' file.txt | |
awk '{printf "%-20s %5d\\n", $1, $2}' file格式化输出为对齐的表格 | 中级 | awk '{printf "%-20s %8.2f\\n", $1, $2}' report.txt | |
awk 'BEGIN{OFS="|"} {print $1, $2, $3}' file设置输出字段分隔符(OFS),常用于格式化表格输出 | 中级 | awk 'BEGIN{OFS="|"} {print $1, $2, $3}' data.txt | |
awk 'BEGIN {FPAT="[^,]*|\"[^\"]*\""} {print $1}' file使用 FPAT 处理带引号的 CSV 字段 | 高级 | awk 'BEGIN {FPAT="[^,]*|\"[^\"]*\""} {print $1}' complex.csv | |
awk '{$1=$1; print}' file重新格式化行(清理多余空白) | 基础 | awk '{$1=$1; print}' messy.txt |