sed 使用总结

为什么要使用 sed

sed 全名叫 stream editor,流编辑器(也叫行编辑器),其处理文本的方式为一行一行的,不同于 vi 等全屏编辑器;主要用途为通过匹配一个或多个正则表达式来对文本进行处理,实现过滤和转换文本。

语法

命令的格式:

1
sed \[options\] \`AddressCommand\` file

Address 表示 sed 处理的范围,比如某几行、以’[‘开头的行等;Command 表示所要执行的命令,Address 和 Command 之间没有空格或其他符号。比如:

1
sed '5,30d' /etc/passwd

sed 的执行过程:

  1. 按顺序逐行将文件读入到内存中;
  2. 然后,它执行为该行指定的所有操作,并在完成请求的修改之后将该行放回到内存中,以将其转储至终端;
  3. 完成了这一行上的所有操作之后,它读取文件的下一行,然后重复该过程直到它完成该文件。

其中有几个关键点:

  1. 输出可以被重定向到另一文件中,以保存变化;
  2. 源文件(默认地)保持不被修改;
  3. sed 默认读取整个文件并对其中的每一行进行修改,不过,可以按需要将操作限制在指定的行上。

几个常用的 options:

  • -n - quiet 模式,suppress automatic printing of pattern space
    sed 默认输出是将每一行的内容输出到屏幕上,一般要配合-n 参数不让其显示不需要的。
  • -i - 直接修改原文件
  • -e script - 可以同时执行多个脚本
  • -f /path/to/sed_script - 指定 sed 命令脚本
  • -r - 使用扩展正则表达式

几个主要的 Command:

  • d - 删除符合条件的行。
  • p - 显示符合条件的行,sed 默认会把处理的文本一行行输出到终端,因此 p 命令相当于把指定的行多输出一次。
  • a \string - 在指定的行后面追加新行,内容为 string,内容里可以添加\n 来换行。
  • i \string - 在指定行前面添加新行,内容为 string。
  • r FILE - 将指定的文件的内容添加到符合条件的行后。
  • w FILE - 将指定范围内的行另存至目标文件中。
  • s /pattern/string/修饰符 - 查找并替换,默认只替换每行中第一次被模式匹配到的字符串
    修饰符主要有:g - 全局替换,i - 忽略字符大小写。
    替换命令的’/‘符号可以用其他字符替换,只要三个分隔符一样即可,如:
    1
    2
    s@pattern@string@修饰符 
    s#pattern#string#修饰符
  • & - 引用模式,匹配整个串

使用示例

部分命令格式在 MAC 下不支持,最好在 Linux 下测试。

选择指定行执行命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 删除第2行到第3行的内容(包括第2行和第3行,不会修改原文件)
sed '2,3d' /etc/passwd
# 删除第2行及其后的1行
sed '2,+1d' /etc/passwd1
# 从第1行删除到最后1行
sed '1,$d' /etc/passwd
# 匹配1个区间
sed '/2019-07-22/,/2019-07-24/d' test.txt
# 在第一行前插入一行文本
sed -i '1 i\abc' text.txt
# 在最后一行后插入一行文本
sed -i '$ a\abc' test.txt
# 在指定行后添加新行,注意&代表pattern
sed 's/pattern/&\n/g' test.txt
# 在指定行前添加新行
sed 's/pattern/\n&/g' test.txt
# 在匹配行前插入一行文本
sed -i '/pattern/ i "插入字符串"' test.txt
# 在匹配行后插入一行文本
sed -i '/pattern/ i "插入字符串"' test.txt
# 在指定行后添加文件内容
sed '1,+1rtest.txt' test.txt
# 删除以nologin结尾的行
sed '/nologin$/d' /etc/passwd
# 删除文本中空行和空格组成的行一级#号注释的行,包括#前都是空格的
grep -v '^\s*#' test.txt | sed '/^[[:space:]]*$/d'

在指定行中执行命令

1
2
3
4
5
6
7
8
# 删除行首空格
sed 's/^[]*//g' test.txt
sed 's/^ *//g' test.txt
sed 's/^[[:space:]]*//g' test.txt
# 使用变量替换
sed -e 's/$var1/$var2/g' test.txt
# 将结果中的多余空格替换为一个:分隔,-P表示按POSIX格式输出
df -P | sed -r 's/[[:space:]]+/:/g'