Sed-命令使用技巧

使用 sed 时, 主要要注意两点:

  • 匹配
  • 动作

匹配, 可以是直接的行号, 行的范围, 也可以是正则表达式匹配.

而动作, 可以为替换, 也可以为插入.

动作指令有:

  • s/foo/bar/g, 替换
  • /pattern/d, 删除
  • /pattern/i text, 匹配行之前插入一行
  • /pattern/a text, 匹配行之后插入一行
  • /pattern/p, 打印匹配的行

注意需要开启 -E-r 选项, 才能用扩展正则表达式. (但也相当有限)

Sed 的处理逻辑

Sed 编辑器读取数据流时, 会基于换行符的位置将数据分成行, 然后再一次处理一行.

若要处理多行, 则需要用到几个特殊命令 (此时不再是一个换行符分成一行):

  • N, 将数据流中的下一行加进来创建一个多行组
  • D, 删除多行组中的一行
  • P, 打印多行组中的一行

模式空间

Pattern space 指 sed 当前要处理的 “行”(不一定是单行内容). 其会保存待检查的文本.

保持空间

Hold space, 可以临时保存一些行.

sed 所支持的正则表达式

字符匹配:
    .:匹配任意单个字符。
    [abc]:匹配字符集中的任意一个字符(a、b 或 c)。
    [^abc]:匹配除字符集中的任意一个字符(a、b 或 c)之外的任意字符。
    [a-z]:匹配字符范围内的任意一个小写字母。
    [A-Z]:匹配字符范围内的任意一个大写字母。
    [0-9]:匹配字符范围内的任意一个数字。

重复匹配:
    *:匹配前一个元素零次或多次。
    +:匹配前一个元素一次或多次。
    ?:匹配前一个元素零次或一次。
    {n}:匹配前一个元素恰好 n 次。
    {n,}:匹配前一个元素至少 n 次。
    {n,m}:匹配前一个元素至少 n 次但不超过 m 次。

锚点和边界:
    ^:匹配行的开头位置。
    $:匹配行的结尾位置。
    \b:匹配单词边界。
    \B:匹配非单词边界。

分组和引用:
    ():将多个元素组合成一个子表达式。
    \n:引用第 n 个子表达式(n 是一个数字)。

转义字符:
    \:转义特殊字符。

单行 next 命令, 定位到匹配行的下一行

如一个文本内容为:

1
2
3
4
5
This is the header line.

This is a data line.

This is the last line.

若要删除 header 的下一行:

1
2
3
4
5
$ sed '/header/{n;d}' data1.txt
This is the header line.
This is a data line.

This is the last line.

(使用多个指令时用 {} 包裹, 用 ; 分隔)

多行 next 命令, 将匹配到的下一行加入到当前模式空间

如一个文本内容为:

1
2
3
4
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.

运行:

1
$ sed '/first/{N; s/\n/ /}' data2.txt

多行删除命令 D, 删除模式空间中的第一行

文本:

1
2
3
4
5
6
$ cat data5.txt

This is the header line.
This is a data line.

This is the last line.

需要删除第一行前的空白行:

1
sed '/^$/{N; /header/D}' data5.txt

多行打印命令 P, 打印模式空间中的第一行

文本:

1
2
3
4
5
$ cat data3.txt
On Tuesday, the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.
Thank you for your attendance.

运行:

1
2
$ sed -n 'N ; /System\nAdministrator/P' data3.txt
On Tuesday, the Linux System

不打印没有匹配上的行

-n, --quiet 参数:

1
2
3
4
5
6
7
$ sed '/Aparna/p' text
Hilesh, 1001
Bharti, 1002
Aparna, 1003
Aparna, 1003
Harshal, 1004
Keyur, 1005

启用 -n 之后:

1
2
$ sed -n '/Aparna/p' text
Aparna, 1003

向文件指定行之前插入一行文本

a “insert” 指令.

一个文件 text 内容为:

1
2
3
4
5
Hilesh, 1001
Bharti, 1002
Aparna, 1003
Harshal, 1004
Keyur, 1005

若向第一行插入 Employee, EmpId:

1
2
3
4
5
6
7
$ sed '1i Employee, EmpId' text
Employee, EmpId
Hilesh, 1001
Bharti, 1002
Aparna, 1003
Harshal, 1004
Keyur, 1005

(此时并没有修改文件内容, 而是输出到 STDOUT)

向文件指定行之后插入一行文本

1
$ sed -i '1a ---------------'  empFile

a “append” 指令.

向文件匹配到的行之后插入一行文本

1
$ sed -i '/hello/a ---------------'  empFile

直接修改文件内容

-i, --in-place[=SUFFIX]:

1
$ sed -i '1i Employee, EmpId' text

文本替换

1
sed 's/a/A/g' text 

常用修饰符包括:

  • g, “global”, 替换掉一行中所有匹配的内容
  • number, 一个数字, 若一行中匹配到了 n 次, 才会执行替换操作

使用 {} 的作用

主要目的就是为了使 寻址 作用于多条命令.

用到 \ 反斜线的地方

只有 i\ (insert), a\ (append), c\ (change), 这三个地方用到了反斜线.


Sed-命令使用技巧
http://example.com/2024/03/08/Sed-命令使用技巧/
作者
Jie
发布于
2024年3月8日
许可协议