Skip to content

Latest commit

 

History

History
167 lines (152 loc) · 7.89 KB

sed.md

File metadata and controls

167 lines (152 loc) · 7.89 KB

简介

  • sed 是一个流编辑器
  • 模式空间: 默认使用, 每次读取都会刷新
  • 保持空间: 默认包含一个换行符, 可以使用其做一些复杂操作

基本流程

  1. 读取一行, 存入模式空间
  2. 对模式空间的内容执行脚本
  3. 输出模式空间的内容
  4. 如果还有下一行, 调到第一步, 否则, 退出

常用参数

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 会基础使用即可, 复杂的能读懂即可
  • 会使用基本命令就足够了,太复杂的一般也用不到