【Linux命令】sed(流式文本编辑器)

sed(Stream Editor)是 Linux/Unix 中一个强大灵活流式文本编辑器。它逐行处理输入(文件或管道输入),根据指定的规则修改文本,并将结果输出(默认到标准输出)。sed 的核心优势在于使用正则表达式进行模式匹配和文本转换,尤其擅长执行查找替换删除行插入/追加文本等批量操作。

核心概念:

  1. 流式处理: 按行读取输入,应用命令,输出结果。
  2. 模式空间: 当前正在处理的行会被读入这个缓冲区。
  3. 命令: 告诉 sed 对模式空间中的内容做什么操作(如替换、删除、打印)。
  4. 地址: 指定命令作用于哪些行(行号、行号范围、正则表达式匹配的行)。省略地址则命令应用于每一行。
  5. 不直接修改原文件(默认): sed 默认将处理结果输出到标准输出(屏幕)。使用 -i 选项才能直接修改源文件(谨慎使用!)。

基本语法:

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

常用选项:

  • -e 'script':指定要执行的 sed 命令/脚本。可以多次使用。
  • -f 'script-file':指定包含 sed 命令的脚本文件。
  • -i[SUFFIX]原地编辑文件,直接修改源文件。
    • -i:直接修改,不备份(风险高!)。
    • -i.bak:修改前创建以 .bak 为后缀的备份文件(推荐!)。
  • -n抑制默认输出。通常与 p 命令(打印)结合使用,只输出处理过的行。
  • -r-E:使用扩展正则表达式(支持 +, ?, |, () 等,无需转义),语法更简洁(强烈推荐)。
  • -l N:设置行长度为 N 字符后换行(较少用)。

常用命令:

  • s/pattern/replacement/flags替换命令(最常用)。
    • pattern:要查找的正则表达式。
    • replacement:替换成的文本。
    • flags:可选标志,控制替换行为:
      • g:全局替换(一行中所有匹配项),默认只替换每行第一个匹配项。
      • p:如果替换成功,则打印模式空间的内容(常与 -n 连用)。
      • iI:忽略 pattern 的大小写(GNU sed 扩展)。
      • 数字:替换第 n 个匹配项。
      • w file:将成功替换的行写入指定文件。
  • d删除当前模式空间的内容(行),并开始处理下一行。
  • p打印当前模式空间的内容。
  • a\text在匹配行之后追加一行(或多行)text
  • i\text在匹配行之前插入一行(或多行)text
  • c\text将匹配行替换为指定的 text(整行替换)。
  • y/src/dst/字符转换,类似 tr。将 src 中的每个字符转换为 dst 中对应位置的字符。长度必须相等。
  • q [exit-code]立即退出 sed 处理流。
  • r file读取指定文件的内容并插入到匹配行之后。
  • w file当前模式空间的内容写入到指定文件。
  • =: 打印当前行号(在单独的一行输出)。

使用示例:

  1. 简单替换(每行第一个匹配项):

    sed 's/apple/orange/' fruits.txt  # 将每行第一个 "apple" 替换为 "orange" (输出到屏幕)
    
  2. 全局替换(所有匹配项):

    sed 's/apple/orange/g' fruits.txt  # 将每行所有 "apple" 替换为 "orange"
    
  3. 删除行:

    sed '3d' data.txt          # 删除第 3 行
    sed '2,5d' data.txt        # 删除第 2 到第 5 行
    sed '/^#/d' config.conf    # 删除所有以 # 开头的行(注释行)
    sed '/^$/d' text.txt       # 删除所有空行
    
  4. 打印特定行:

    sed -n '10p' largefile.log  # 仅打印第 10 行 (-n 抑制默认输出, p 命令打印)
    sed -n '5,10p' report.txt   # 打印第 5 到第 10 行
    sed -n '/error/p' logfile   # 打印所有包含 "error" 的行
    
  5. 原地编辑文件(务必小心!推荐备份):

    sed -i.bak 's/old_string/new_string/g' important.cfg  # 修改文件,并创建备份 important.cfg.bak
    sed -i '/^DEBUG/d' script.sh                         # 直接删除所有以 DEBUG 开头的行(无备份!风险高!)
    
  6. 在指定行后追加文本:

    sed '3a\This line is added after line 3.' file.txt
    # 在第 3 行之后添加一行 "This line is added after line 3."
    
  7. 在指定行前插入文本:

    sed '2i\This line is inserted before line 2.' file.txt
    
  8. 替换整行:

    sed '/server_name/c\server_name newdomain.com;' nginx.conf
    # 将包含 "server_name" 的行替换为 "server_name newdomain.com;"
    
  9. 使用扩展正则表达式(-r-E):

    sed -r 's/([0-9]{3})-([0-9]{3})-([0-9]{4})/\1.\2.\3/' phones.txt
    # 将 123-456-7890 格式的电话号码改为 123.456.7890
    # 不用 -r 需要写:sed 's/\([0-9]\{3\}\)-\([0-9]\{3\}\)-\([0-9]\{4\}\)/\1.\2.\3/'
    
  10. 只对匹配模式的行进行替换:

    sed '/admin/s/active/inactive/' users.txt
    # 仅在包含 "admin" 的行中,将 "active" 替换为 "inactive"
    
  11. 引用匹配内容(&\1, \2, …):

    sed 's/[0-9]\+/Number: &/' data.txt
    # 在所有数字串前加上 "Number: " (如 123 -> Number: 123)
    sed -r 's/(name): (.*)/\2: \1/' mapping.txt
    # 交换 "name: value" 格式为 "value: name" (如 name: Alice -> Alice: name)
    
  12. 使用不同的分隔符: 当模式或替换字符串包含 / 时,可以换用其他分隔符(如 :, |, @):

    sed 's:/usr/local/bin:/usr/bin:' pathlist.txt
    sed 's|http://old.site|https://new.site|g' links.html
    

重要提示:

  • 备份!备份!备份! 使用 -i 选项直接修改文件前,强烈建议使用 -i.bak 创建备份,或者在不带 -i 的情况下先测试命令。
  • 测试命令: 在应用 -i 之前,先在不修改源文件的情况下运行 sed 命令,确认输出符合预期。
  • 转义特殊字符:patternreplacement 中,正则表达式的特殊字符(如 ., *, ^, $, [, ], \, &)通常需要转义(使用 \)才能表示字面意义。在 replacement 中,& 代表整个匹配内容,\1, \2 等代表捕获组。
  • 扩展正则表达式: 使用 -r (GNU sed) 或 -E (BSD/macOS sed) 可以让正则表达式更易读易写。

sed 功能非常丰富,这些示例涵盖了最常用的场景。掌握 s(替换)、d(删除)、p(打印)命令和地址定位是高效使用 sed 的关键。对于更复杂的文本处理任务,可以结合多个命令或使用 sed 脚本文件。

你可能感兴趣的:(Linux,linux)