Linux 文件处理器 sed 和 awk 详细讲解

一、sed 命令详解​

1.1 sed 命令概述​

sed(Stream Editor,流编辑器)是 CentOS 7 中用于对文本进行流式处理的强大工具。它逐行读取输入文本(文件或标准输入),根据预设的编辑命令对每行内容进行处理,然后输出处理结果。sed 常用于文本替换、删除、插入、修改等操作,在脚本编写和系统管理等批量文本处理场景中应用广泛。​

1.2 sed 命令语法结构​

基本语法为:​

TypeScript

取消自动换行复制

sed [选项] '编辑命令' [文件名]​

  • 选项:用于调整 sed 的行为。
  • 编辑命令:指定对文本的具体操作,如替换、删除、插入等。
  • 文件名:指定要处理的文件,若省略文件名,sed 将从标准输入读取数据。

1.3 常用选项详解​

|-----|----------------------|---------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|
| 选项​ | 全称​ | 功能描述​ | 示例​ |
| -n​ | --quiet, --silent​ | 默认情况下,sed 会输出处理后的每一行;使用-n选项则仅输出经过特定命令处理且被显示的行​ | sed -n '2p' file.txt:只输出文件中第 2 行的内容​ |
| -e​ | --expression=script​ | 允许在一行中指定多个编辑命令 ,可多次使用 -e 追加命令​ | sed -e's/abc/def/' -e '3d' file.txt:先将文件中的 "abc" 替换为 "def",再删除第 3 行​ |
| -i​ | --in-place=SUFFIX​ | 直接修改原文件,而不是输出到标准输出。使用时需谨慎,建议提前备份文件;若指定SUFFIX,则会在修改前为原文件创建备份(备份文件名为原文件名加SUFFIX)​ | sed -i '.bak' s/old/new/g file.txt:将文件file.txt中的 "old" 替换为 "new",并创建名为file.txt.bak的备份文件​ |
| -f​ | --file=script-file​ | 从指定的脚本文件中读取编辑命令​ | 若有脚本文件sed_script.sed,内容为s/hello/world/,则执行sed -f sed_script.sed file.txt,将file.txt中的 "hello" 替换为 "world"​ |
| -r​ | --regexp-extended​ | 使用扩展正则表达式,部分元字符无需转义,简化复杂正则的书写​ | sed -r's/([0-9]+)/[\1]/' file.txt:将文件中连续的数字字符串加上中括号,若使用普通正则,()需转义为\(\)​ |
| -s​ | --separate​ | 当处理多个文件时,将每个文件视为独立输入,不将多个文件内容连接处理​ | 执行sed -s's/start/end/' file1.txt file2.txt,会分别对file1.txt和file2.txt进行替换,而不是将两个文件内容合并后处理​ |

1.4 常用编辑命令及示例​

1.4.1 替换命令(s)​

功能:用于替换文本中的字符串,是 sed 最常用的命令之一。​

语法:s/原字符串/新字符串/[g],其中g表示全局替换(若不使用g,则只替换每行中第一个匹配的字符串)。​

示例:​

  • 将文件test.txt中所有的 "apple" 替换为 "banana":

TypeScript

取消自动换行复制

sed's/apple/banana/g' test.txt​

  • 仅替换每行中第一个 "hello" 为 "hi":

TypeScript

取消自动换行复制

sed's/hello/hi/' test.txt​

  • 按指定分隔符替换,如将/etc/passwd文件中以冒号分隔的第三个字段(用户 ID)为 1001:

TypeScript

取消自动换行复制

sed's/:/1001:2/' /etc/passwd​

  • 使用其他分隔符替换,避免与替换内容冲突,如将 "/home/user/doc/file.txt" 中的 "/" 替换为 "_":

TypeScript

取消自动换行复制

sed's|/|_|g' /home/user/doc/file.txt​

1.4.2 删除命令(d)​

功能:删除指定的行。​

语法:行号d 或 地址范围d,其中行号可以是具体的数字,地址范围可以用逗号分隔起始行号和结束行号。​

示例:​

  • 删除文件test.txt的第 3 行:

TypeScript

取消自动换行复制

sed '3d' test.txt​

  • 删除文件中第 2 行到第 5 行的内容:

TypeScript

取消自动换行复制

sed '2,5d' test.txt​

  • 删除包含 "error" 的行:

TypeScript

取消自动换行复制

sed '/error/d' log.txt​

  • 删除以 "#" 开头的注释行:

TypeScript

取消自动换行复制

sed '/^#/d' config.ini​

1.4.3 插入命令(i)和追加命令(a)​

功能:i用于在指定行前插入内容,a用于在指定行后追加内容。​

语法:行号i 或 行号a,然后在新行输入要插入或追加的内容,以Ctrl + D结束输入;也可直接在命令后添加内容,如行号i 内容。​

示例:​

  • 在文件test.txt的第 2 行前插入 "new line":

TypeScript

取消自动换行复制

sed '2i new line' test.txt​

  • 在文件末尾追加一行内容:

TypeScript

取消自动换行复制

sed '$a This is the last line' test.txt​

  • 在包含 "target" 的行前插入新行:

TypeScript

取消自动换行复制

sed '/target/i insert line before target' file.txt​

1.4.4 修改命令(c)​

功能:将指定的行替换为新的内容。​

语法:行号c,然后输入新内容,以Ctrl + D结束;也可直接在命令后添加新内容,如行号c 新内容。​

示例:​

  • 将文件test.txt的第 3 行修改为 "modified line":

TypeScript

取消自动换行复制

sed '3c modified line' test.txt​

  • 将包含 "old_content" 的行修改为 "new_content":

TypeScript

取消自动换行复制

sed '/old_content/c new_content' file.txt​

1.5 sed 高级应用场景​

1.5.1 批量修改文件内容​

在项目开发中,可能需要批量修改多个文件中的某个字符串。例如,将项目中所有.html文件里的 "old_domain.com" 替换为 "new_domain.com":​

TypeScript

取消自动换行复制

sed -i's/old_domain.com/new_domain.com/g' *.html​

注意,使用-i选项时务必先备份文件,防止误操作导致数据丢失。若要同时备份文件,可使用sed -i.bak's/old_domain.com/new_domain.com/g' *.html,会生成.bak后缀的备份文件。​

1.5.2 结合正则表达式处理复杂文本​

当处理包含特殊字符或复杂格式的文本时,可借助正则表达式。比如,从日志文件中提取所有以 "ERROR" 开头的行,并将错误代码(数字部分)替换为 "XXXX":​

TypeScript

取消自动换行复制

sed -n '/^ERROR/s/ERROR [0-9]*/ERROR XXXX/p' error.log​

这里-n选项配合p命令(打印匹配行),只输出经过替换后的错误行。若要提取 IP 地址(格式为xxx.xxx.xxx.xxx),可使用:​

TypeScript

取消自动换行复制

sed -n's/.*\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p' log.txt​

此命令通过正则表达式提取每行中的 IP 地址并输出。​

二、awk 命令详解​

2.1 awk 命令概述​

awk是一种强大的文本处理编程语言,它以字段为单位对文本进行处理,能够轻松实现数据提取、格式化输出、统计计算等功能。awk 的工作模式是逐行读取输入文本,根据指定的规则将每行文本拆分成字段,然后对字段进行操作和处理。它在数据分析、日志处理、报表生成等场景中发挥着重要作用。​

2.2 awk 命令语法结构​

基本语法为:​

TypeScript

取消自动换行复制

awk [选项] '模式 {动作}' [文件名]​

  • 选项:常用选项用于设置字段分隔符等参数。
  • 模式:用于筛选符合条件的行,模式可以是正则表达式、关系表达式或行号范围等。如果省略模式,默认对所有行执行动作。
  • 动作:是 awk 执行的具体操作,包括打印字段、计算、赋值等,动作由一系列语句组成,用大括号{}括起来。
  • 文件名:指定要处理的文件,若省略文件名,awk 将从标准输入读取数据。

2.3 常用选项详解​

|-----|-----------------------|-------------------------------|----------------------------------------------------------------------------------------------|
| 选项​ | 全称​ | 功能描述​ | 示例​ |
| -F​ | --field-separator=fs​ | 指定字段分隔符,默认是空格或制表符 ,fs为自定义分隔符​ | awk -F: '{print 1, 3}' /etc/passwd:以冒号为分隔符,打印/etc/passwd文件中每行的用户名(第 1 个字段)和用户 ID(第 3 个字段)​ |
| -v​ | --assign=var=value​ | 定义或赋值变量,在 awk 脚本中使用​ | awk -v num=10 '{if (1 \> num) print 1}' file.txt:定义变量num为 10,输出文件中第一个字段大于 10 的行的第一个字段​ |
| -f​ | --file=script-file​ | 从指定的脚本文件中读取 awk 脚本​ | 若有脚本文件awk_script.awk,内容为{print $0},则执行awk -f awk_script.awk file.txt,输出file.txt的所有行​ |
| -F​ | --lint​ | 对 awk 脚本进行语法检查,输出可能存在的问题​ | awk --lint'script.awk':检查script.awk脚本的语法错误​ |
| -W​ | --help, --usage​ | 显示 awk 的帮助信息和使用方法​ | awk --help:查看 awk 命令的详细帮助文档​ |

2.4 常用内置变量及示例​

awk 提供了多个内置变量,方便对文本字段进行操作:​

  • $0:表示整行文本。
  • 1,

    2,...:表示每行的第 1 个字段、第 2 个字段,以此类推。

  • NF:表示当前行的字段数量。
  • NR:表示当前处理的行号。
  • FS:字段分隔符(默认是空格或制表符),可通过-F选项或在脚本中设置。
  • OFS:输出字段分隔符,用于设置输出时字段之间的分隔符。

示例:​

  • 以冒号为分隔符,打印/etc/passwd文件中每行的用户名(第 1 个字段)和用户 ID(第 3 个字段):

TypeScript

取消自动换行复制

awk -F: '{print 1, 3}' /etc/passwd​

  • 统计文件的行数:

TypeScript

取消自动换行复制

awk 'END {print NR}' file.txt​

这里END是 awk 的特殊模式,表示处理完所有行后执行动作。​

  • 设置输出字段分隔符为逗号,打印文件中每行的前两个字段:

TypeScript

取消自动换行复制

awk -F' ' 'BEGIN {OFS=","} {print 1, 2}' file.txt​

BEGIN是 awk 的另一个特殊模式,在处理文件内容前执行动作,这里用于设置输出分隔符。​

2.5 典型操作及示例​

2.5.1 数据提取​

从日志文件access.log中提取所有访问 IP 地址(假设 IP 地址在每行的第 1 个字段):​

TypeScript

取消自动换行复制

awk '{print $1}' access.log​

若日志格式为IP地址 - 时间 - 访问路径,以空格为分隔符,可使用:​

TypeScript

取消自动换行复制

awk -F' - ' '{print $1}' access.log​

  • 提取包含特定字符串的行的某个字段,如从日志中提取包含 "GET" 请求的行的 URL(假设 URL 在第 4 个字段):

TypeScript

取消自动换行复制

awk '/GET/ {print $4}' access.log​

2.5.2 数据统计​

计算文件中某列数据的总和。例如,有一个记录销售额的文件sales.txt,格式为产品名称 销售额,计算总销售额:​

TypeScript

取消自动换行复制

awk '{sum += $2} END {print sum}' sales.txt​

这里通过sum += $2将每行的销售额累加到sum变量中,处理完所有行后,在END模式下输出总和。​

  • 统计每个产品的销售数量,文件orders.txt格式为产品ID 销售数量:

TypeScript

取消自动换行复制

awk '{count[1\] += 2} END {for (id in count) {print id, count[id]}}' orders.txt​

使用数组count以产品 ID 为下标统计销售数量,最后输出每个产品 ID 及其总销售数量。​

2.5.3 数据格式化输出​

将/etc/passwd文件中的用户名和用户 ID 按照指定格式输出:​

TypeScript

取消自动换行复制

awk -F: '{printf "用户名: %s, 用户ID: %s\n", 1, 3}' /etc/passwd​

printf函数用于格式化输出,与 C 语言中的printf函数类似,可指定输出格式。​

  • 输出一个简单的表格,文件students.txt格式为姓名 年龄 成绩:

TypeScript

取消自动换行复制

awk -F' ' 'BEGIN {printf "%-10s %-5s %-5s\n", "姓名", "年龄", "成绩"} {printf "%-10s %-5d %-5d\n", 1, 2, $3}' students.txt​

BEGIN模式先输出表头,然后逐行按照指定格式输出学生信息,%-10s表示左对齐,宽度为 10 个字符的字符串格式。​

2.6 awk 高级应用场景​

2.6.1 复杂条件筛选​

从日志文件中筛选出访问次数大于 100 的 IP 地址及其访问次数。假设日志文件access.log格式为IP地址 访问次数:​

TypeScript

取消自动换行复制

awk '{count[1\] += 2} END {for (ip in count) {if (count[ip] > 100) {print ip, count[ip]}}}' access.log​

这里使用数组count统计每个 IP 地址的总访问次数,在END模式下遍历数组,筛选出符合条件的 IP 地址并输出。​

  • 筛选出成绩大于 80 分且年龄小于 25 岁的学生信息,文件students.txt格式为姓名 年龄 成绩:

TypeScript

取消自动换行复制

awk -F' ' '{if (2 \< 25 \&\& 3 > 80) print $0}' students.txt​

2.6.2 多文件处理​

同时处理多个文件,并对文件中的数据进行合并统计。例如,有多个销售数据文件sales1.txt、sales2.txt等,格式均为产品名称 销售额,计算所有文件中产品的总销售额:​

TypeScript

取消自动换行复制

awk '{sum[1\] += 2} END {for (product in sum) {print product, sum[product]}}' sales*.txt​

通过数组sum按产品名称统计销售额,最后输出每个产品的总销售额。​

  • 合并多个文件的特定字段,文件file1.txt和file2.txt格式均为字段1 字段2,将两个文件的字段 1 合并输出:

TypeScript

取消自动换行复制

awk 'FNR==NR {a[NR]=1; next} {print a\[FNR\], 1}' file1.txt file2.txt​

FNR表示当前文件的行号,NR表示总的行号,先读取file1.txt将字段 1 存入数组a,再读取file2.txt并结合数组a输出合并结果。​

三、sed 与 awk 的对比与结合使用​

3.1 功能对比​

|------|----------------------------------|---------------------------|
| 工具​ | 功能特点​ | 适用场景​ |
| sed​ | 侧重于文本的编辑和修改,如字符串替换、行的增删改等操作​ | 文本格式转换、批量替换字符串、删除或修改特定行等​ |
| awk​ | 擅长数据的提取、分析和统计,能够以字段为单位对文本进行复杂处理​ | 数据分析、日志处理、报表生成、数据计算等​ |

相关推荐
牧以南歌〆1 小时前
在Ubuntu主机中修改ARM Linux开发板的根文件系统
linux·arm开发·驱动开发·ubuntu
互联网搬砖老肖1 小时前
运维打铁: MongoDB 数据库集群搭建与管理
运维·数据库·mongodb
Antonio9152 小时前
【音视频】HLS简介与服务器搭建
运维·服务器·音视频
夜月yeyue2 小时前
设计模式分析
linux·c++·stm32·单片机·嵌入式硬件
kfepiza2 小时前
Debian的`/etc/network/interfaces`的`allow-hotplug`和`auto`对比讲解 笔记250704
linux·服务器·网络·笔记·debian
艾伦_耶格宇3 小时前
【docker】-1 docker简介
运维·docker·容器
R.X. NLOS3 小时前
VS Code远程开发新方案:使用SFTP扩展解决Remote-SSH连接不稳定问题
运维·服务器·ssh·debug·vs code
cuijiecheng20183 小时前
Ubuntu下布署mediasoup-demo
linux·运维·ubuntu
独行soc5 小时前
2025年渗透测试面试题总结-2025年HW(护网面试) 33(题目+回答)
linux·科技·安全·网络安全·面试·职场和发展·护网
java龙王*6 小时前
开放端口,开通数据库连接权限,无法连接远程数据库 解决方案
linux