sed

title

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 : 退出sed
  • r : 读取文件内容
  • 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文本处理的重要工具,掌握其用法可以大大提高文本编辑和处理的效率。


powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 12:47:16

results matching ""

    No results matching ""