sed
sed(Stream Editor)是一个文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作。
基本语法
sed [OPTIONS] 'command' 输入文件
sed [OPTIONS] -e 'command1' -e 'command2' 输入文件
sed [OPTIONS] -f scriptfile 输入文件
常用选项
-n
: 使用安静(silent)模式。在一般sed的用法中,所有来自STDIN的资料一般都会被列出到屏幕上。但如果加上-n参数后,则只有经过sed特殊处理的那一行(或者动作)才会被列出来-e
: 直接在指令列模式上进行sed的动作编辑-f
: 直接将sed的动作写在一个档案内,-f filename 则可以执行filename内的sed动作-r
: sed的动作支援的是延伸型正规表示法的语法(预设是基础正规表示法语法)-i
: 直接修改读取的档案内容,而不是由屏幕输出--backup[=SUFFIX]
: 在使用-i时创建备份文件
基本命令
a
: 新增(append) - 在指定行后面新增内容i
: 插入(insert) - 在指定行前面插入内容c
: 取代(change) - 替换指定行的内容d
: 删除(delete) - 删除指定行p
: 列印(print) - 打印指定行(通常与-n一起使用)s
: 取代(substitute) - 字符串替换y
: 转换(transform) - 字符对字符的转换q
: 退出sedr
: 读取文件内容w
: 写入文件
基本使用示例
显示特定行
# 显示第2行
sed -n '2p' file.txt
# 显示第2到第5行
sed -n '2,5p' file.txt
# 显示最后一行
sed -n '$p' file.txt
# 显示包含pattern的行
sed -n '/pattern/p' file.txt
删除操作
# 删除第2行
sed '2d' file.txt
# 删除第2到第5行
sed '2,5d' file.txt
# 删除最后一行
sed '$d' file.txt
# 删除空行
sed '/^$/d' file.txt
# 删除包含pattern的行
sed '/pattern/d' file.txt
替换操作
# 替换每行第一个匹配
sed 's/old/new/' file.txt
# 替换每行所有匹配
sed 's/old/new/g' file.txt
# 只替换第2个匹配
sed 's/old/new/2' file.txt
# 替换并显示替换的行
sed 's/old/new/p' file.txt
新增和插入
# 在第2行后面新增一行
sed '2a\新增的内容' file.txt
# 在第2行前面插入一行
sed '2i\插入的内容' file.txt
# 在匹配行后面新增
sed '/pattern/a\新增的内容' file.txt
# 在文件末尾新增
sed '$a\新增的内容' file.txt
高级用法
地址范围
# 行号范围
sed '2,5s/old/new/g' file.txt
# 模式范围
sed '/start/,/end/s/old/new/g' file.txt
# 从模式到行号
sed '/pattern/,10s/old/new/g' file.txt
# 从行号到模式
sed '5,/pattern/s/old/new/g' file.txt
正则表达式
# 使用基本正则表达式
sed 's/[0-9]*/NUMBER/' file.txt
# 使用扩展正则表达式
sed -r 's/[0-9]+/NUMBER/' file.txt
# 反向引用
sed 's/\([a-z]*\) \([a-z]*\)/\2 \1/' file.txt
# 匹配行首和行尾
sed 's/^/>>> /' file.txt # 行首添加
sed 's/$/<<</' file.txt # 行尾添加
多个命令
# 使用分号分隔
sed 's/old1/new1/; s/old2/new2/' file.txt
# 使用-e选项
sed -e 's/old1/new1/' -e 's/old2/new2/' file.txt
# 使用换行符
sed '
s/old1/new1/
s/old2/new2/
' file.txt
实用应用场景
配置文件修改
# 修改配置文件中的参数
sed -i 's/^#Port 22/Port 22/' /etc/ssh/sshd_config
# 注释掉某行
sed -i 's/^Port/#Port/' /etc/ssh/sshd_config
# 修改IP地址
sed -i 's/192\.168\.1\.100/192.168.1.200/g' config.txt
# 修改端口号
sed -i 's/port=8080/port=9090/g' app.conf
日志处理
# 提取特定日期的日志
sed -n '/2023-12-25/p' /var/log/messages
# 删除旧日志条目
sed -i '/2023-11/d' /var/log/app.log
# 格式化日志输出
sed 's/\[ERROR\]/[🔴ERROR🔴]/g' /var/log/app.log
# 提取IP地址
sed -n 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' access.log
代码处理
# 删除C++注释
sed 's|//.*||g' source.cpp
# 删除空行和注释行
sed '/^$/d; /^#/d' script.sh
# 统一缩进(将tab转换为4个空格)
sed 's/\t/ /g' source.py
# 添加行号
sed = file.txt | sed 'N;s/\n/: /'
数据处理
# CSV文件处理 - 交换第1列和第2列
sed 's/\([^,]*\),\([^,]*\),\(.*\)/\2,\1,\3/' data.csv
# 电话号码格式化
sed 's/\([0-9]\{3\}\)\([0-9]\{3\}\)\([0-9]\{4\}\)/(\1) \2-\3/' phone.txt
# URL提取
sed -n 's/.*href="\([^"]*\)".*/\1/p' webpage.html
# 删除HTML标签
sed 's/<[^>]*>//g' webpage.html
高级技巧
保持空间(Hold Space)
# 将模式空间复制到保持空间
sed 'h' file.txt
# 将保持空间追加到模式空间
sed 'H' file.txt
# 将保持空间复制到模式空间
sed 'g' file.txt
# 交换模式空间和保持空间
sed 'x' file.txt
# 反转文件行序
sed '1!G;h;$!d' file.txt
条件执行
# 只在匹配行执行替换
sed '/pattern/s/old/new/' file.txt
# 在匹配行的下一行执行操作
sed '/pattern/{n;s/old/new/;}' file.txt
# 跳过匹配行
sed '/pattern/!s/old/new/' file.txt
分支和标签
# 使用标签和分支
sed ':a;s/\([0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' numbers.txt
# 条件分支
sed '/pattern/b skip; s/old/new/; :skip' file.txt
实用脚本示例
配置文件备份和修改脚本
#!/bin/bash
# config_modifier.sh
CONFIG_FILE="/etc/myapp.conf"
BACKUP_FILE="${CONFIG_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
# 创建备份
cp "$CONFIG_FILE" "$BACKUP_FILE"
echo "备份创建: $BACKUP_FILE"
# 修改配置
sed -i '
s/^debug=.*/debug=false/
s/^port=.*/port=8080/
s/^#log_level=.*/log_level=info/
' "$CONFIG_FILE"
echo "配置文件已更新"
日志清理脚本
#!/bin/bash
# log_cleanup.sh
LOG_DIR="/var/log"
CUTOFF_DATE=$(date -d "30 days ago" +%Y-%m-%d)
# 删除30天前的日志条目
for logfile in "$LOG_DIR"/*.log; do
if [[ -f "$logfile" ]]; then
echo "清理 $logfile 中 $CUTOFF_DATE 之前的日志"
sed -i "/$CUTOFF_DATE/,\$!d" "$logfile"
fi
done
批量文件处理脚本
#!/bin/bash
# batch_process.sh
DIRECTORY="$1"
if [[ ! -d "$DIRECTORY" ]]; then
echo "用法: $0 <目录>"
exit 1
fi
# 处理目录中的所有.txt文件
find "$DIRECTORY" -name "*.txt" -type f | while read -r file; do
echo "处理文件: $file"
# 删除空行
sed -i '/^$/d' "$file"
# 统一行尾符
sed -i 's/\r$//' "$file"
# 删除行末空格
sed -i 's/[[:space:]]*$//' "$file"
echo "完成: $file"
done
代码重构脚本
#!/bin/bash
# refactor_code.sh
# 批量重命名变量
find . -name "*.cpp" -o -name "*.h" | xargs sed -i 's/\boldVarName\b/newVarName/g'
# 更新函数调用
find . -name "*.py" | xargs sed -i 's/old_function(/new_function(/g'
# 更新import语句
find . -name "*.py" | xargs sed -i 's/from old_module import/from new_module import/g'
echo "代码重构完成"
常见错误和解决方案
特殊字符处理
# 正确处理路径分隔符
sed 's|/old/path|/new/path|g' file.txt
# 处理包含空格的字符串
sed 's/old string/new string/g' file.txt
# 转义特殊字符
sed 's/\$/DOLLAR/g' file.txt # 转义$符号
sed 's/\[/BRACKET/g' file.txt # 转义[符号
备份和恢复
# 创建备份
sed -i.bak 's/old/new/g' file.txt
# 指定备份扩展名
sed -i'.backup' 's/old/new/g' file.txt
# 批量恢复备份
for backup in *.bak; do
mv "$backup" "${backup%.bak}"
done
性能优化
# 处理大文件时限制行数
sed -n '1,1000p' large_file.txt | sed 's/old/new/g'
# 早期退出
sed '/pattern/q' file.txt
# 使用更高效的模式
sed -n '/pattern/p' file.txt # 而不是 sed '/pattern/!d' file.txt
调试技巧
测试sed命令
# 先不修改文件,查看输出
sed 's/old/new/g' file.txt
# 使用echo测试
echo "test old string" | sed 's/old/new/g'
# 显示详细执行过程
sed -n 'l' file.txt # 显示特殊字符
# 显示行号
sed -n '=' file.txt
调试复杂脚本
# 在脚本中添加调试信息
sed '
/pattern/{
l
s/old/new/
l
}' file.txt
相关命令
awk
: 更强大的文本处理工具grep
: 文本搜索工具tr
: 字符转换工具cut
: 列提取工具sort
: 排序工具uniq
: 去重工具
sed是Linux文本处理的重要工具,掌握其用法可以大大提高文本编辑和处理的效率。