ZetCode

Linux sed 命令

最后修改于 2025 年 4 月 2 日

sed (stream editor) 命令是 Linux 中一个强大的文本处理工具,它对输入流执行基本和高级的文本转换。它逐行读取文本,应用指定的命令,并输出结果。本指南通过 20 个实用示例介绍 sed 的基础知识,涵盖从基本替换到高级文本操作。掌握 sed 可以无需手动干预即可高效地批量编辑文件和流。

基本 sed 语法

sed 的基本语法是 sed [options] 'commands' [input-file]。Sed 对输入的每一行进行操作,应用一个或多个编辑命令。默认情况下,sed 会输出到 stdout,而不修改输入文件。本示例展示了基本的 sed 用法模式。

basic_syntax.sh
# 1. Simple text substitution (replace first occurrence per line)
echo "hello world" | sed 's/hello/hi/'
# Output: hi world

# 2. Editing file in-place (with backup)
sed -i.bak 's/foo/bar/' file.txt

# 3. Multiple commands
echo "hello world" | sed -e 's/hello/hi/' -e 's/world/there/'
# Output: hi there

# 4. Using different delimiters
echo "path/to/file" | sed 's|/|_|g'
# Output: path_to_file

# 5. Print only modified lines (-n with p flag)
seq 1 5 | sed -n 's/3/three/p'
# Output: three

示例 1 展示了基本的替换语法 s/pattern/replacement/。示例 2 使用 `-i` (in-place) 选项和备份文件进行就地文件编辑。示例 3 使用 -e 组合多个命令。示例 4 使用替代分隔符以提高可读性。示例 5 展示了如何抑制默认输出并仅打印修改后的行。

文本替换示例

替换是 sed 最常见的操作,使用 s 命令。这些示例使用不同的标志和模式演示了各种替换技术。掌握替换可以实现强大的文本转换。

substitution_examples.sh
# 6. Global replacement (all occurrences)
echo "hello hello world" | sed 's/hello/hi/g'
# Output: hi hi world

# 7. Replace only 2nd occurrence
echo "one two two three" | sed 's/two/2/2'
# Output: one two 2 three

# 8. Case-insensitive substitution
echo "Hello hello HELLO" | sed 's/hello/hi/i'
# Output: hi hello HELLO

# 9. Using groups in replacement
echo "John Doe" | sed 's/\([^ ]*\) \([^ ]*\)/\2, \1/'
# Output: Doe, John

# 10. Using & in replacement (matched pattern)
echo "123 abc" | sed 's/[0-9]*/& &/'
# Output: 123 123 abc

示例 6 显示了带有 g 标志的全局替换。示例 7 仅替换第二个匹配项。示例 8 使用 i 进行不区分大小写的匹配。示例 9 使用分组重新排序名称。示例 10 展示了 & 如何代表匹配的文本。

行选择和删除

Sed 可以在应用操作之前按行号或模式选择特定行。这些示例演示了行寻址和删除技术。精确的行选择对于目标文本处理至关重要。

line_selection.sh
# 11. Delete lines containing pattern
seq 1 5 | sed '/3/d'
# Output: 1 2 4 5

# 12. Delete lines NOT containing pattern
seq 1 5 | sed '/3/!d'
# Output: 3

# 13. Delete specific line number
seq 1 5 | sed '3d'
# Output: 1 2 4 5

# 14. Delete range of lines (2-4)
seq 1 5 | sed '2,4d'
# Output: 1 5

# 15. Delete from line to end of file
seq 1 5 | sed '3,$d'
# Output: 1 2

示例 11 删除匹配模式的行。示例 12 使用 ! 反转匹配。示例 13 按行号删除。示例 14 显示范围删除。示例 15 删除从第 3 行到末尾 ($) 的行。

高级转换

Sed 支持高级文本转换,包括多行操作、暂存区 (hold space) 操作和条件执行。这些示例演示了 sed 在复杂任务中的强大编辑功能。

advanced_operations.sh
# 16. Append text after match
echo -e "line1\nline2" | sed '/line1/a\appended text'
# Output:
# line1
# appended text
# line2

# 17. Insert text before match
echo -e "line1\nline2" | sed '/line2/i\inserted text'
# Output:
# line1
# inserted text
# line2

# 18. Change entire line
echo -e "old1\nold2" | sed '/old1/c\new line'
# Output:
# new line
# old2

# 19. Transform specific characters (like tr)
echo "hello" | sed 'y/abcdefghij/0123456789/'
# Output: 74llo

# 20. Multi-line pattern matching (N command)
echo -e "line1\nline2\nline3" | sed '/line1/{N;s/line1\nline2/replaced/}'
# Output:
# replaced
# line3

示例 16 在匹配项后追加文本。示例 17 在匹配项前插入文本。示例 18 替换整行。示例 19 转换字符,类似 tr。示例 20 使用 N 命令演示多行操作。

实用的 sed 脚本

这些实用示例使用 sed 解决了现实世界的文本处理问题。它们结合了多种技术,以展示 sed 在生产环境中的多功能性。

practical_scripts.sh
# 21. Remove blank lines
echo -e "line1\n\nline2" | sed '/^$/d'
# Output:
# line1
# line2

# 22. Remove leading whitespace
echo "    text" | sed 's/^[ \t]*//'
# Output: text

# 23. Remove trailing whitespace
echo "text    " | sed 's/[ \t]*$//'
# Output: text

# 24. Remove HTML tags
echo "<p>Hello <b>world</b></p>" | sed 's/<[^>]*>//g'
# Output: Hello world

# 25. Number lines (like nl)
echo -e "one\ntwo\nthree" | sed '=' | sed 'N;s/\n/ /'
# Output:
# 1 one
# 2 two
# 3 three

示例 21 删除空行。示例 22-23 修剪空白。示例 24 删除 HTML 标签。示例 25 通过组合两个 sed 命令对行进行编号。

sed 与正则表达式

Sed 的真正强大之处在于将其命令与正则表达式结合。这些示例演示了复杂的模式匹配和替换技术。

regex_examples.sh
# 26. Match whole words only
echo "cart part smart" | sed 's/\bpart\b/replace/g'
# Output: cart replace smart

# 27. Extract text between patterns
echo "before [extract] after" | sed 's/.*\[\([^]]*\)\].*/\1/'
# Output: extract

# 28. Convert DOS line endings (CRLF to LF)
sed 's/\r$//' dosfile.txt > unixfile.txt

# 29. Convert lowercase to uppercase
echo "hello" | sed 's/.*/\U&/'
# Output: HELLO

# 30. Format phone numbers
echo "Call 1234567890" | sed 's/\([0-9]\{3\}\)\([0-9]\{3\}\)\([0-9]\{4\}\)/(\1) \2-\3/'
# Output: Call (123) 456-7890

示例 26 匹配整个单词。示例 27 提取括号之间的文本。示例 28 转换行结束符。示例 29 将文本转换为大写。示例 30 使用捕获组格式化电话号码。

sed 分支和流程控制

Sed 提供了分支命令,用于在编辑脚本中实现复杂的流程控制。这些示例演示了 sed 中的条件操作和循环。

branching_examples.sh
# 31. Skip lines containing pattern
echo -e "include\nskip\ninclude" | sed '/skip/b; s/include/replaced/'
# Output:
# replaced
# skip
# replaced

# 32. Multiple commands on matched lines
echo -e "line1\nspecial\nline2" | sed '/special/{s/line/xxx/;p;d}'
# Output:
# line1
# xxxspecial
# line2

# 33. Conditional replacement (only if another match exists)
sed '/start/,/end/ s/foo/bar/' file.txt

# 34. Label and branch example
echo -e "a\nb\na\nc" | sed ':top; /a/{s/a/x/; b top}'
# Output:
# x
# b
# x
# c

# 35. Quit after first match
seq 1 10 | sed '/5/q'
# Output: 1 2 3 4 5

示例 31 跳过匹配行的处理。示例 32 对匹配项应用多个命令。示例 33 显示基于范围的替换。示例 34 演示标签和分支。示例 35 在第一次匹配后退出。

sed 暂存区和模式空间

Sed 维护一个模式空间(当前行)和一个暂存区(临时存储)以进行高级文本操作。这些示例演示了多行处理技术。

hold_space_examples.sh
# 36. Reverse file lines (tac)
seq 1 3 | sed '1!G;h;$!d'
# Output:
# 3
# 2
# 1

# 37. Double space lines
echo -e "a\nb\nc" | sed 'G'
# Output:
# a
#
# b
#
# c

# 38. Join pairs of lines
echo -e "a\nb\nc\nd" | sed 'N;s/\n/ /'
# Output:
# a b
# c d

# 39. Print duplicate lines only
echo -e "a\nb\na\nc" | sed -n '$!N; /^\(.*\)\n\1$/p; D'
# Output: a

# 40. Number non-empty lines
echo -e "a\n\nb\nc" | sed '/./=' | sed '/./N; s/\n/ /'
# Output:
# 1 a
# 3 b
# 4 c

示例 36 反转文件行。示例 37 双倍行距。示例 38 连接行对。示例 39 查找重复项。示例 40 只对非空行进行编号。这些示例展示了 sed 的高级缓冲区操作。

最佳实践

在将 sed 命令应用于重要文件之前,请先使用示例输入进行测试。对于复杂的脚本,请使用 -e 以提高可读性。在开发过程中,请在就地编辑 (-i) 前使用备份。为了方便将来维护,请使用 # 为复杂的 sed 脚本添加注释。对于极其复杂的文本处理任务,请考虑使用 perlawk

资料来源

从这些资源中了解更多信息:GNU sed 手册sed 手册页,以及sed & awk 书籍

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Linux 教程