sed
命令给我的感觉是 Linux 中最复杂的命令之一,难度堪比编程语言中的正则表达式。不过复杂背后带来的是强大的功能。在掌握了它的用法后,相当于是得到了一件在 Linux 系统上处理文本的利器。
sed 命令格式
sed [选项]... {脚本} [输入文件]...
如果没有给出 -e
,--expression
,-f
,或者 --file
选项,第一个非选项参数会被当作 sed
命令的脚本来解释。所有余下的参数是输入文件的名称。如果没有指定输入文件,默认会从标准输入读取内容。
sed 命令示例
光看上面的命令格式可能还不明就里,直接来看例子。假设要把 test.txt 文件中的 abc 小写字母替换为 ABC 大写字母:
sed 's/abc/ABC/' test.txt
上面的命令会输出执行替换后的内容,但还没有真正去修改文件内容,可以当作是命令处理脚本的预览。如果要直接修改文件内容,需要使用 -i
选项:
sed -i 's/abc/ABC/' test.txt
再去看看文件内容,符合条件的文字一定被修改了。命令脚本中的 /
是定界符,除了这个符号,:
也可以拿来做定界符:
sed 's:abc:ABC:' test.txt
除了替换字符,sed
命令还可以用来清理文件中的空白行:
sed '/^$/d' test.txt
删除指定行,比如要删除第 3 行:
sed '2d' test.txt
按行区间来删除,比如从 3 行到最后一行都删除:
sed '2,$d' test.txt
删除以 abc 开头的行:
sed '/^abc/d' test.txt
匹配 abc 并给匹配到的内容加上中括号:
sed 's/abc/[&]/' test.txt
搭配 grep
命令批量替换指定的文件:
sed -i 's/zzx/zzxworld/g' `grep "zzx" -rl --include="*.htm" ./`
sed 命令选项
缩写 | 完整名称 | 说明 |
---|---|---|
-n |
--quiet , --silent |
不自动打印模式空间的内容。 |
-e 脚本 |
--expression= 脚本 |
添加脚本到将要执行的命令。 |
-f 脚本文件 |
--file= 脚本文件 |
添加脚本文件的内容到即将执行的命令。 |
--follow-symlinks |
处理已存在文件时跟随链接。 | |
-i [SUFFIX] |
--in-place [=SUFFIX] |
编辑已存在的文件(如果提供了SUFFIX作为后缀则做备份)。 |
-l N |
--line-length= N |
指定 l 命令需要的自动换行长度。 |
--posix |
禁用所有GNU插件。 | |
-E -r |
--regexp-extended |
在脚本中使用扩展正则表达式(为了可移植性,请使用符合POSIX的-E)。 |
-s |
--separate |
将多个文件分别看待,而非统一视作同个连续的流。 |
--sandbox |
在沙箱模式下操作。 | |
-u |
--unbuffered |
从输入文件中读取最少量的数据并更频繁地刷新输出缓冲区。 |
-z |
--null-data |
用 NUL 字符分割行。 |
--help |
显示这个帮助并退出。 | |
--version |
输出版本信息并退出。 |
sed
命令提供的选项不多,核心在于脚本命令。sed
主要的脚本命令如下:
名称 | 说明 |
---|---|
: label |
b 和 t 命令的标签。 |
#comment |
注释将会延长到下一个新行(或者一个 -e 脚本片段的结尾)。 |
} |
一个 { } 块的闭括号。 |
= |
答应当前行的行号。 |
a \ text |
追加 text , text 可以通过预先写入反斜杠来嵌入新行。 |
i \ text |
插入 text , text 可以通过预先写入反斜杠来嵌入新行。 |
q [exit-code] |
立即退出 sed 脚本而不处理其他输入,除非自动打印没有禁用使得当前模式空间将会被打印。[exit-code] 是 GNU 插件。 |
Q [exit-code] |
立即退出 sed 脚本而不处理其他输入。这是一个GNU插件。 |
r 文件名 |
从文件名读取内容并追加到最后。 |
R 文件名 |
从文件名读取一行并追加到最后。每次调用这个命令就从文件中读取一行。 |
{ |
开始一个命令块,以 } 符号结束。 |
b label |
程序跳转到 label 处;如果 label 被省略,跳转到脚本尾部。 |
c \ text |
用 text 代替选择的行, text 可以通过预先写入反斜杠来嵌入新行。 |
d |
删除模式空间。 |
D |
如果模式空间包含新行,在 d 命令发布之后开始一个新的普通循环。否则删除模式空间中的 text 直到新行,并且在不读入新行的情况下,用结果的模式空间开始一个循环。 |
h H |
复制 / 追加模式空间到保存空间。 |
g G |
复制 / 追加保存空间到模式空间。 |
l |
用直观明确的格式列出当前行。 |
l width |
用直观明确的格式列出当前行,在 width 字符处结束。这是一个 GNU 插件。 |
n N |
读取 / 追加下一行输入到模式空间。 |
p |
输出当前的模式空间。 |
P |
输出直到遇到当前模式空间的第一个嵌入的换行符。 |
s/regexp/replacement/ |
尝试与模式空间匹配 regexp ,如果成功,用 replacement 代替匹配的部分 。replacement 可能包含特殊字符 & 来引用模式空间中匹配的部分,而特殊字符 \1 到 \9 则引用 regexp 中对应匹配的子表达式。 |
t label |
自上次输入行读取之后并且上次执行了 t 或者 T 命令之后,如果一个 s/// 被成功替换,那么跳转到 label 处;如果 label 被忽略,跳转到脚本结尾。 |
T label |
自上此输入行读取之后并借上次执行了 t 或者 T 命令之后,如果一个 s/// 被成功替换,那么跳转到 label 处;如果 label 被忽略,跳转到脚本结尾。这是一个 GNU 插件。 |
w filename |
将当前的模式空间写入到 filename 中。 |
W filename |
写入当前模式空间的第一行到 filename 中。这是一个 GNU 插件。 |
x |
交换模式空间和保存空间的内容。 |
y/source/dest/ |
将模式空间中显示为 source 的字符用 dest 字符来写出。 |