Sed 命令

 

命令格式

sed [options] [address1[,address2]]command [file, ...]

相同地址可以执行多个命令,每条命令单独一行,用大括号括起来。注意,右括号必须单独一行。

sed address{
    n
    p
}

也可以将多个命令放入一行,命令间用 ; 分隔。

sed address{n;p}

地址

  • no addresses
    在所有行上执行命令.

  • 1 address
    只在匹配地址的那一行执行命令.

  • 2 addresses
    在包含第一和第二地址之间的行上执行命令.

  • !
    在地址之后,命令之前,插入一个 ! 表示在所有不匹配的地址上执行命令.

地址的匹配规则

  • 语法是:addr1, addr2

  • addr1 匹配的地址总是有效的,哪怕 addr2 的地址在 addr1 之前.

  • 如果 addr2 是一个正则表达式,addr1 所匹配的行不会被正则表达式检查.

sed 支持的地址类型

  • number
    匹配指定的行.

  • first~step
    匹配从 first 行开始每 step 行,例如 sed -n 1~2p 表示打印所有奇数行,sed -n 2~5p 表示从第 2 行开始,每隔 5 行匹配一次.

  • $
    匹配最后一行.

  • /regexp/
    匹配正则表达式匹配的行.

  • \cregexpc
    匹配正则表达式匹配的行,c 可以是任意字符.

GNU sed 支持的 2-address 格式

  • addr1, +N
    匹配 addr1 和后续的 N 行.

  • addr1, ~N
    匹配 addr1 和后续直到是 N 的倍数的行.

命令

零地址命令

  • # 注释

零或一地址命令

  • =
    打印当前行号.

  • a\
    text
    追加文本 (append),文本除了最后一行外,每一行都以 \ 结尾.

  • i\
    text
    插入文本 (insert),格式与 a\ 相同.

  • q
    立即退出 sed 命令.

  • r <file>
    追加从文件中读取的文本.

二地址命令 (地址范围)

  • { COMMANDS }
    执行一组命令,命令以 ; 分隔.

  • c\
    text
    将匹配的行用指定文本替换 (change),格式与 a\ 相同.

  • d/D
    删除 pattern space,并开始下个循环 (delete).

  • h/H
    复制/追加 pattern sapce 到 hold space (Hold).

  • g/G
    复制/追加 hold space 到 pattern space (Get).

  • l
    打印当前行的 pattern sapce (look).

  • n/N
    读入/追加下一行到 pattern space.

  • p
    打印当前 pattern sapce.

  • s/regexp/replacement/
    对 pattern space 的内容进行替换.

例子

在单个地址上执行多个命令

$ seq 3 | sed -n '2{s/2/X/; p}'
X

删除文件中的匹配模式的行

# dry run
sed '/pattern/d' file

# 在原文件中删除,并备份原文件到 bak 文件
sed -i.bak '/pattern/d' file

在当前目录的所有文件中查找 :9000 并替换为 /launchpad

# dry run
sed -n 's,:9000,/launchpad,p' *
# 或
sed -n '/:9000/s,,/launchpad,p' *
  • 第一个命令行是直接使用替换命令,如果没有指定地址,默认在所有行上进行匹配和替换。

  • 第二个命令行是先使用模式匹配来定位地址,然后在地址上执行替换命令,如果替换命令没有指定匹配模式,则使用与地址相同的匹配模式。

使用模式匹配确定地址,对地址的下一行执行命令

# dry run
sed -n "/search-pattern/ {n; s/regexp/replacement/p}" filename

# in-place replacement
sed -i '' -e "/search-pattern/ {n; s/regexp/replacement/}" filename

在指定地址后追加文本

$ seq 3 | sed '2a\
hello\
world
'
1
2
hello
world
3

# GNU sed extentions
$ seq 3 | sed '2a hello'
1
2
hello
3

# GNU sed extentions
$ seq 3 | sed -e '2a\' -e 'hello'
1
2
hello
3

$ HI='hello'
$ seq 3 | sed -e '2a\' -e "$HI"