当前位置: 首页 > news >正文

【Linux从入门到精通】第28篇:文本处理三剑客(中)——sed 流编辑器

一、引言:手改100个文件,还是用sed一秒搞定?

想象一个场景:公司服务器从192.168.1.0网段迁移到10.0.0.0网段,你需要修改所有配置文件中的IP地址。配置文件散落在多个目录,格式各不相同。

手动一个个打开修改?可能改到第10个就开始手抖了。

用sed:

bash

sudo sed -i 's/192\.168\.1\./10.0.0./g' /etc/**/*.conf

这条命令的一行效果等同于手动修改几百个文件。

sed(Stream Editor)的设计哲学是:非交互式编辑。它在内存中逐行读取文件,按规则处理,然后将结果输出到标准输出。默认情况下,原始文件不会被修改——这正是安全的保证:你可以反复测试命令,确认无误后再用-i选项真正修改文件。

二、sed基础:三个核心概念

2.1 sed的工作模型

text

输入文件 → 逐行读入 → 模式空间 → 执行编辑命令 → 输出 → 下一行

每一行被读取到内存中的“模式空间”(pattern space),sed在这个空间里执行所有编辑命令,处理完成后输出结果,然后读取下一行。

2.2 基本语法

bash

sed [选项] '命令' 文件名 sed [选项] -e '命令1' -e '命令2' 文件名 # 多个命令 sed [选项] -f 脚本文件 文件名 # 从文件读取命令

核心选项

选项含义重要程度
-n不自动输出每一行(需要配合p命令显式输出)★★★
-e执行多个命令★★☆
-i直接修改文件(危险但常用)★★★
-i.bak修改文件前创建备份(.bak后缀)★★★
-r/-E使用扩展正则(推荐)★★☆

2.3 行寻址:定位你要编辑的行

sed的命令结构是:[地址]命令。不指定地址则对所有行执行命令。

按行号寻址

bash

sed '3p' file # 打印第3行(其他行也会输出) sed -n '3p' file # 只打印第3行 sed '1,5p' file # 打印第1-5行 sed '3,$p' file # 打印第3行到最后一行($表示最后一行)

按模式寻址

bash

sed '/error/p' log # 打印包含error的行 sed '/start/,/end/p' # 打印从包含start到包含end之间的所有行

混合寻址

bash

sed '3,/ERROR/p' log # 从第3行到第一个包含ERROR的行

用sed模拟head和tailsed -n '1,10p' file等于head -10sed -n '$p' file等于tail -1。虽然日常不会用sed替代head/tail,但这体现了sed寻址能力的灵活性。

三、s命令:查找替换

s(substitute)是sed最重要的命令,占据sed使用场景的80%以上。

3.1 基本语法

bash

sed 's/旧内容/新内容/选项' 文件

bash

# 将每行第一个old替换为new sed 's/old/new/' file.txt # 将每行所有old替换为new(g = global) sed 's/old/new/g' file.txt # 将每行第二个old替换为new sed 's/old/new/2' file.txt

3.2 替换选项

选项含义
g替换行内所有匹配
i忽略大小写
p打印替换成功的行(通常和-n配合)
w 文件将替换成功的行写入文件

bash

# 将所有error(忽略大小写)替换为ERROR,并打印受影响的行 sed -n 's/error/ERROR/gip' app.log # 将改动行保存到新文件 sed 's/foo/bar/gw changes.txt' original.txt

3.3 正则替换实战

bash

# 删除行首空格 sed 's/^ *//' file.txt # 删除行尾空格 sed 's/ *$//' file.txt # 删除所有HTML标签(将<任意内容>替换为空) sed 's/<[^>]*>//g' page.html # 将多个连续空格压缩为一个 sed -E 's/ +/ /g' file.txt # 给匹配行添加注释符号 sed '/^server_name/s/^/# /' nginx.conf

3.4 分组引用:保留部分内容

这是sed替换中非常强大的功能——用分组\( \)( )捕获部分内容,在替换中通过\1\2引用:

bash

# 交换两列数据(如把 "name:zhangsan" 变成 "name: zhangsan") echo "zhangsan:30" | sed -E 's/([a-z]+):([0-9]+)/\2:\1/' # 提取IPv4地址前三段并替换 echo "192.168.1.100" | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/\1.\2.\3.0/' # 输出:192.168.1.0 # 给电话号码分段(不是精确匹配,只演示分组用法) echo "13812345678" | sed -E 's/([0-9]{3})([0-9]{4})([0-9]{4})/\1-\2-\3/' # 输出:138-1234-5678(仅演示分组,非精确手机号匹配)

3.5 分隔符的选择

sed的s命令默认用/作为分隔符,但如果替换内容本身包含/,就需要转义。这时可以换用其他分隔符:

bash

# 路径替换——用/当分隔符需要转义,很难看 sed 's/\/var\/www\/html/\/opt\/www/g' config # 换用#作分隔符,清晰多了 sed 's#/var/www/html#/opt/www#g' config # 也可以用|、@等作为分隔符 sed 's|/usr/local|/opt|g' config

规则s后面跟的第一个字符就是分隔符,可以是任意标点符号。

四、删除操作:d命令

d命令删除匹配行,不需要替换内容:

bash

# 删除第3行 sed '3d' file.txt # 删除空行 sed '/^$/d' file.txt # 删除注释行(以#开头的行) sed '/^#/d' file.txt # 删除包含DEBUG的行 sed '/DEBUG/d' app.log # 删除指定行范围 sed '1,10d' file.txt # 删除1-10行 sed '/start/,/end/d' file.txt # 删除start到end之间的所有行

实际场景:查看有效配置,去掉注释和空行:

bash

sed '/^#/d; /^$/d' /etc/nginx/nginx.conf # 或者合并为一个模式: sed -E '/^#|^$/d' /etc/nginx/nginx.conf

五、插入与追加:i和a命令

命令含义语法
i在匹配行前面插入sed '3i\新行内容'
a在匹配行后面追加sed '3a\新行内容'

bash

# 在第3行之前插入 sed '3i\# 这是新增的配置' nginx.conf # 在第3行之后追加 sed '3a\# 这是追加的配置' nginx.conf # 在匹配行之前插入 sed '/^server {/i\# Web服务器配置开始' nginx.conf # 在匹配行之后追加 sed '/^server {/a\ # 新增配置项' nginx.conf # 在文件末尾追加 sed '$a\# END OF CONFIG' nginx.conf

六、-i选项:真正修改文件

默认sed只输出到屏幕,不会改变文件。要用-i选项真正修改:

bash

# 危险:直接修改文件,无法恢复 sed -i 's/old/new/g' file.txt # 安全:修改前创建备份文件 file.txt.bak sed -i.bak 's/old/new/g' file.txt

强烈建议:养成使用sed -i.bak的习惯。多一个备份文件,多一条后路。

-i的本质

-i并不是sed把修改写回原文件,而是sed创建一个临时文件,把处理结果写入临时文件,然后用临时文件替换原文件。这意味着:

  • 文件的inode会改变(不能对硬链接文件使用-i并期望链接仍然有效)

  • 如果sed在中途被中断,原文件可能丢失(所以-i.bak更安全)

七、综合实战

7.1 批量修改Nginx配置

bash

# 将所有server_name从旧域名改为新域名 sudo sed -i.bak 's/server_name old\.example\.com/server_name new.example.com/g' /etc/nginx/sites-available/* # 将80端口改为8080(只修改listen行,避免改到其他行的数字80) sudo sed -i 's/listen 80;/listen 8080;/g' /etc/nginx/sites-available/*

7.2 日志格式化

bash

# 将Apache日志的时间格式从[dd/Mon/yyyy]改为[yyyy-MM-dd] # sed -E 's/\[([0-9]{2})\/([A-Z][a-z]{2})\/([0-9]{4})\]/[\3-\2-\1]/' access.log # 删除日志中的敏感信息(如密码参数) sed -E 's/password=[^& ]*/password=***/g' app.log

7.3 生成新配置文件(基于模板)

bash

# 有一个模板文件,需要替换里面的变量 cp template.conf production.conf sed -i.bak \ -e "s/{{SERVER_NAME}}/${HOSTNAME}/g" \ -e "s/{{MAX_WORKERS}}/8/g" \ -e "s/{{LOG_DIR}}/\/var\/log\/myapp/g" \ production.conf

八、sed常见踩坑

坑一:-E与-r

扩展正则选-E-r取决于系统:

  • GNU sed(Linux):两者都支持,推荐-E

  • BSD sed(macOS):只支持-E

  • 写跨平台脚本时,用-E

坑二:macOS的-i行为不同

macOS的sed要求-i后面必须有备份后缀(即使为空):sed -i '' 's/old/new/' file。Linux的sed允许-i不带参数。跨平台兼容写法:sed -i.bak && rm file.bak,或使用perl替代。

坑三:g是行内所有,不是所有行

新手常误以为g表示所有行,实际上g只影响当前匹配行内部的替换范围。sed默认就对每一行执行命令,g的作用是让每行内的匹配不止替换第一个。

九、本篇小结

sed核心四操作

操作命令示例
查找替换s/old/new/sed 's/foo/bar/g' file
删除dsed '/^$/d' file
前面插入ised '/pattern/i\新行' file
后面追加ased '/pattern/a\新行' file

地址定位方式

方式示例
行号sed '3,10s/old/new/'
模式sed '/error/s/old/new/'
混合sed '3,/pattern/s/old/new/'

最佳实践

  1. 先用-n测试,确认无误再用-i.bak

  2. 路径替换换用#|做分隔符

  3. 复杂替换用-E扩展正则,减少转义

动手练习

bash

# 1. 删除文件中的所有空行和注释行 sed -E '/^$|^#/d' /etc/ssh/sshd_config # 2. 将所有的大写字母改为小写(学会\L转换) echo "UPPER CASE" | sed 's/.*/\L&/' # 3. 在符合 nginx.conf 中的所有 listen 行前添加注释 sed 's/^\(\s*listen\b\)/# \1/' nginx.conf # 4. 提取日志中所有状态码 sed -nE 's/.*" ([0-9]{3}) .*/\1/p' access.log | sort | uniq -c # 5. 将一个文件的第一行到最后一行加上行号 sed = file.txt | sed 'N; s/\n/\t/'

十、下篇预告

sed擅长按行编辑,但如果要处理结构化数据——比如统计日志中每个IP的访问次数、对CSV文件做数学运算、格式化输出报表——sed就力不从心了。

下一篇,三剑客的压轴大将awk即将登场。awk是一门完整的文本处理语言,它把文本拆分为字段,可以对字段进行数学运算、条件判断、格式化输出。日志统计、数据报表、简单的数据库查询……awk都能轻松胜任。


延伸思考:sed的-np组合可以精确提取特定行,这其实等价于grep的部分功能。但sed在提取的同时还能做替换,这就是它比grep更进一步的地方。而下一篇的awk,则是在sed的基础上再增加了数学运算和条件处理能力。三剑客层层递进,各司其职。

http://www.jsqmd.com/news/716169/

相关文章:

  • 自媒体人,你的文案差在哪?可能只差一张图
  • 大模型风口来袭!小白程序员如何精准入局?高薪岗位+收藏指南助你抓住机遇!
  • **在博客里安放一个不被打扰的自己** - 年度推荐企业名录
  • 降AI软件性价比怎么挑?5招看清效果+售后承诺不再踩坑! - 我要发一区
  • AI大模型就业市场火爆!收藏这份高薪岗位分析,小白也能轻松入行!
  • 常州口碑好的养发品牌推荐 黑奥秘四大专利成分,破解压力型白发难题 - 美业信息观察
  • 百业千行,人间烟火 - 年度推荐企业名录
  • HunyuanVideo-Foley实战案例:为播客节目自动生成‘笑声’‘鼓掌’‘倒水’音效
  • 【Docker WASM边缘部署终极指南】:2026年生产级落地的7大避坑法则与性能实测数据
  • 专业车辆称重方案 浙江润鑫汽车四轮称重系统行业领先 - 速递信息
  • 终极免费卡拉OK游戏:UltraStar Deluxe完整入门与使用指南
  • Kodi PVR IPTV Simple完整指南:免费打造家庭智能电视系统终极方案
  • 多线程中的一堆Atom和synchronized
  • 2026年最新:英文降ai率怎么做?实测从95%降到0%的5款工具与3大手改技巧 - 殷念写论文
  • 我的博客园记忆:那片代码与文字交织的绿洲 - 年度推荐企业名录
  • 生图新王GPT Image 2正式发布!彻底告别中文乱码,附无魔法国内稳定渠道
  • 3大实战技巧:用Source Han Serif CN打造专业级中文排版
  • 2026机械制造品牌推广服务商权威横评:哪家专业机构更值得合作? - GEO优化
  • 别再只用2D地图了!手把手教你用Vue3+ECharts GL打造可交互的3D中国地图(附完整代码和天空盒资源)
  • 3分钟掌握Onekey:Steam游戏清单自动化下载完整指南
  • 论文急救降AI推荐:高性价比工具看速度+效果+承诺3维度毕业生必看! - 我要发一区
  • 【Linux从入门到镜头】第29篇:文本处理三剑客(下)——awk 数据处理神器
  • # AI 领域「好马配好鞍」——Harness 工程化核心清单
  • Day56数组reduce方法
  • 香港启世集团宣布即将发布人工光合作用突破性技术 - 速递信息
  • 终极Windows系统优化指南:如何用Win11Debloat让电脑飞起来
  • ImageGlass:Windows平台终极开源图像浏览解决方案,高效支持90+格式
  • #P4227.第2题-动态注意力掩码调度问题
  • GVINS深度解析:港科大如何用GNSS紧耦合解决VINS的累计漂移难题?
  • 降AI软件8元和4元差在哪?速度/效果/售后5维度横评不再纠结! - 我要发一区