- sed 是一个流编辑器
- 模式空间: 默认使用, 每次读取都会刷新
- 保持空间: 默认包含一个换行符, 可以使用其做一些复杂操作
- 读取一行, 存入模式空间
- 对模式空间的内容执行脚本
- 输出模式空间的内容
- 如果还有下一行, 调到第一步, 否则, 退出
sed script 1.txt # 正常使用
# 若 1.txt 为符号链接, 将操作读取符号链接所指的文件
sed -e script -e script 1.txt # 使用 -e 添加脚本, -e 支持多次使用
sed -f 1.sed 1.txt # 从文件中读取脚本
sed -n script 1.txt # 不输出模式空间的内容
sed -i script 1.txt # 直接在原文件上修改
sed -iabc script 1.txt # 直接在原文件上修改, 并备份到 1.txtabc 中
sed -i --follow-symlinks script 1.txt # 若 1.txt 为符号链接, 修改符号链接所指向的文件
# 默认将修改符号链接, 即修改后不再是符号链接了
sed -r script 1.txt # 使用扩展的正则表达式,默认使用基础的正则表达式
sed -z script 1.txt # 输入行以 \0 区分, 而不是 \n
- script 有无引号,单双引号都行
- script 有空格的时候必须有引号或转义
- script 有 $ 表示末尾的时候需要使用单引号或转义
- script 有 ! 表示 非的时候需要使用单引号或转义
- script 可以使用 {} 包成块, 方便嵌套
- script 可以使用多个命令,用分号分割
- script 里转义字符会被解析
无说明时表示整个文件
* 2p # 输出第二行
* 2,0p # 输出第二行 -- 一般用不上
* 2,1p # 输出第二行 -- 一般用不上
* 2,2p # 输出第二行 -- 一般用不上
* 2,3p # 输出第二行,第三行
* 2,5p # 输出第二行,第三行,第四行,第五行
* 2,+4p # 输出第二行以及接下来四行, 共五行
* 0~2p # 每两行打印第二行, 将打印第 2 4 6 ... 行 -- 一般用不上
* 1~2p # 每两行打印第一行,将打印第 1 3 5 ... 行 -- 一般用不上
* 2~2p # 每两行打印第二行, 将打印第 2 4 6 ... 行 -- 一般用不上
* 3~2p # 每两行打印第三行,将打印第 3 5 7 ... 行 -- 一般用不上
* $p # 输出最后一行
* $,0p # 输出最后一行 -- 一般用不上
* $,1p # 输出最后一行 -- 一般用不上
* 2,$p # 输出第二行到文件末尾
* 2,100p # 输出第二行到文件末尾, 假设文件小于 100 行
* /111/ # 输出匹配到 111 的行, 支持正则表达式
* \c111c # 输出匹配到 111 的行, c 可以使用任意字符
# 主要方便处理 正则表达式 包含 / 的情况
* /111/,/222/ # 输出匹配到 111 的行, 到匹配到 222 的行(包含)
# 222 未匹配到时表示文件末尾
# 开始匹配使用正则表达式时, 不能匹配同一行
* /111/,+4p # 输出匹配到 111 的行以及接下来四行, 共五行
* 0,/111/ # 输出文件开头到匹配到 111 的行
# 如果 /111/ 可以匹配第一行,将只输出第一行
* 1,/111/ # 输出第一行到匹配到 111 的行
# /111/ 不会匹配第一行
操作范围后加 ! 表示不输出
* 2!p # 不输出第二行
addr,~np # 输出匹配到的行直到第 N 行,N 为 n 的整数倍 -- 很复杂, 感觉一般用不上
* # ... 注释
* : ... 定义标签
* = 输出行号
* a ... 行后插入, 忽略后面的空字符, 第一个 \ 不具有转义的效果
* 1a123 # 在第一行(即第二行)后插入123
* 1a\123 # 在第一行(即第二行)后插入123
* 1a 123 # 在第一行(即第二行)后插入123, 将忽略空格
* 1a\ 123 # 在第一行(即第二行)后插入" 123"
* 1a \123 # 在第一行(即第二行)后插入" \123"
* 1a \t2\t # 在第一行(即第二行)后插入" t123"
# 不会解释第一个转义 \t
# 会解释第二个转义 \t
* b ... 跳到标签处,如果标签未指定时,跳到脚本末尾
* c ... 取代所选择的行, 使用和行后插入(a)类似
* d 删除模式空间的内容, 并进入下一循环
* D 删除模式空间的第一行内容, 如果此时模式空间为空,开始下一循环,否则,跳到脚本开始处继续
* e
* f
* g 将保持空间复制到模式空间
* G 将保持空间附加到模式空间
* h 将模式空间复制到保持空间
* H 将模式空间附加到保持空间
* i ... 行前插入, 使用和行后插入(a)类似
* j
* k
* l 列出当前行,标明不可见字符
* m
* n 读取下一行到模式空间
* N 将下一行添加到模式空间内容后
* o
* p 打印模式空间的内容
* P 打印模式空间的第一行内容
* q 退出, sed "2q" 1.txt # 输出第一行,第二行后退出
* Q 退出, sed "2Q" 1.txt # 输出第一行后退出
* r 添加文件的内容, 貌似无法在文件开头添加另一文件的内容
* sed "r2.txt" 1.txt # 每一行后插入 2.txt 的内容
* sed "r/dev/stdin" # 便于和管道或重定向一起使用
* R 行后添加文件中的一行
* sed "R2.txt" 1.txt # 第一行后插入 2.txt 的第一行
# 第二行后插入 2.txt 的第二行, 如果 2.txt 已读完,则不插入
* s 取代
* sed "s/123/456/" 1.txt # 替换第一处
* sed "s/123/456/2" 1.txt # 替换第二处
* sed "s/123/456/2g" 1.txt # 替换第二处及以后
* sed "s/123/456/g" 1.txt # 替换所有
* sed -n "s/123/456/gp" 1.txt # 打印替换后的结果
* sed -n "s/123/456/gw2.txt" 1.txt # 替换后的结果写入文件 2.txt
* sed "s|123|456|" 1.txt # 使用不同的分割符
* sed "s/.*/[&]/" 1.txt # & 用于表示所匹配到的内容
* sed "s/\(1\)/[\1]/" 1.txt # \1 表示第一个字串
* sed -r "s/(1)/[\1]/" 1.txt # \1 表示第一个字串
* sed "s/1/a \t b/" 1.txt # 可以包含 \n \t
* t abc 前一个 s 命令成功会跳转到指定标签 -- 这个有点儿复杂, 感觉一般用不上
* T abc 前一个 s 命令未成功会跳转到指定标签 -- 这个有点儿复杂,感觉一般用不上
* w ... 写模式空间的内容到文件
* sed "1w1.c" 1.txt # 第一行行保存到文件
* W ... 写模式空间的第一行的内容到文件
* x 交换模式空间和保持空间的内容
* y 字符替换, 可以指定操作的行,无法指定替换一行中的第几个
* sed "y/123/456/" 1.txt
* sed "y/1-3/456/" 1.txt
* sed "y/123/4-6/" 1.txt
* sed "y/1-3/4-6/" 1.txt
* z
- a i r R 插入的内容不在模式空间,所以后续的 d 或 D 不会对插入的内容有影响
* sed -n '1!G; h; $p' 1.txt # 逆序输出文件的内容
# 可以用 tac 代替
* sed '=' 1.txt | sed -n "N; s/\n/ /; p" # 添加行号
# 可以用 cat -n 代替
* sed ':start; $q; N; 4,$D; b start' 1.txt # 输出最后的三行
# 可以用 tail -3 代替
* sed '/./,/^$/!d' 3.txt # 删除连续的空行
# 可以用 cat -s 代替
* sed '/./,$!d' 3.txt # 删除文件开头的空行
* sed ':start; /^\n*$/{$d; N; b start}' 3.txt # 删除文件末尾的空行 -- 能理解即可, 太绕了
* sed 's/<[^>]*>//g; /^$/d' 3.txt # 删除 html 标签
- 建议直接使用扩展的正则表达式,也不在乎这么点儿效率
- 保持空间, N D P 会基础使用即可, 复杂的能读懂即可
- 会使用基本命令就足够了,太复杂的一般也用不到