1. 命令介绍
sed,即流编辑器(stream editor),是一种在命令行下对文本进行编辑的工具。它通常用于文本处理、数据转换和提取等任务。sed通过逐行处理输入数据流,并根据用户提供的规则进行操作,可以实现强大的文本处理功能。
2. 基本用法
sed [options] 'command' [file...]
command:
是针对每一行要执行的编辑命令。
file:要替换文本的文件名列表。如果未提供文件名,则从标准输入读取输入。
参数
-e script, --expression=script:在命令行上指定一个或多个编辑命令。
-f script-file, --file=script-file:从指定文件中读取编辑命令。
-i[SUFFIX], --in-place[=SUFFIX]:直接在原始文件上进行编辑,而不是将结果输出到标准输出。可选的 SUFFIX 用于备份原始文件,如-i.bak:设置一个文件名.bak结尾的备份文件。
-n, --quiet, --silent:禁止默认输出。只有当显式请求打印时才会输出。
-r, --regexp-extended:使用扩展的正则表达式语法,sed 可以使用更灵活的正则表达式语法,包括使用 +
、?
、()
等元字符。
-u, --unbuffered:即时写入输出缓冲区,而不是等待缓冲区填满后再写入。
--follow-symlinks:遵循符号链接指向的文件。
--posix:启用 POSIX 兼容模式,限制某些 GNU 扩展功能。
--sandbox:以沙盒模式运行 sed,限制对文件系统的访问权限。
-c, --copy:复制原始文件到标准输出,而不进行编辑。
-b, --binary:以二进制模式打开文件,用于处理二进制文件。
--help:显示帮助信息。
--version:显示版本信息。
编辑命令
a
:append(追加) - 在指定行后面追加文本。
c
:change(更改) - 替换指定行的文本。
d
:delete(删除) - 删除指定行或匹配到的行。
i
:insert(插入) - 在指定行之前插入文本。
p
:print(打印) - 打印指定行或匹配到的行。
s
:substitute(替换) - 查找并替换指定字符串。s/old/new/,将old替换为new。
q
:quit(退出) - 退出 sed
处理过程。
=
:print line numbers(打印行号) - 打印当前行号。
r
:read file(读取文件内容) - 读取文件内容并插入到指定位置。
w
:write file(写入文件内容) - 将匹配的行写入到文件中。
y
:transform characters(转换字符) - 根据字符映射表转换字符。
示例
1. 删除空白行:
sed -i '/^$/d' file.txt
/^$/
是一个正则表达式模式,匹配空白行。
d
是删除命令,表示删除匹配到的行。
2. 替换文本中的字符串:
sed -i.bak 's/old/new/' file.txt
将文本中的 old
字符串替换为 new
字符串并创建一个文件名.bak结尾的备份文件。
3. 在指定行前插入文本:
sed '2i\Inserting text before line 2' file.txt
'2i\Inserting text before line 2'
:2
表示行号,i\
表示在指定行之前插入文本。\
用来转义字符,在这里表示换行。
4. 在指定行后追加文本:
sed '3a\Appending text after line 3' file.txt
'3a\Appending text after line 3'
:这是 sed
的编辑命令部分。在单引号内部,3
表示行号,a
表示在指定行之后追加文本,\
用来转义,Appending text after line 3
是要追加的文本内容。
5. 仅打印匹配行的行号:
sed -n '/pattern/=' file.txt
使用 -n
参数禁止默认输出,然后使用 =
命令打印匹配到的行号。
6. 删除匹配行后的内容:
sed '/pattern/{n; d;}' file.txt
对于匹配到的行,先读取下一行(n
),然后删除当前行(d
),即删除匹配行后的所有内容。
7. 提取指定行范围内的内容:
sed -n '10,20p' file.txt
使用 -n
参数禁止默认输出,然后使用 10,20p
命令打印文件的第 10 行到第 20 行的内容。
8. 删除匹配行之外的内容:
sed '/pattern/!d' file.txt
使用 !d
命令,删除所有不匹配 pattern
的行
9. 使用正则表达式进行替换:
sed 's/[0-9]\+/*/g' file.txt
使用正则表达式将文本中的所有数字替换为 *
符号
10. 使用扩展的正则表达式语法替换文本:
sed -r 's/colou?r/color/g' file.txt
把文件中所有的 color
和 colour
都替换成 color
11. 添加行号:
sed = filename.txt | sed 'N;s/\n/ /' > filename_with_line_numbers.txt
这个命令会在 filename.txt
文件中的每一行前添加行号,生成一个新的文件 filename_with_line_numbers.txt
。详细解释:
sed = filename.txt
:这部分命令给 filename.txt
文件中的每一行添加行号。=
命令打印当前行号,然后跟随着一个换行符。换行符使得每个行号单独成行。这个命令的输出是每一行的行号,行号与原始文件中的文本分隔开。
sed 'N;s/\n/ /'
:这部分命令将两行合并为一行。N
命令读取下一行,并将其追加到当前模式空间中。然后,s/\n/ /
命令将新行的换行符替换为一个空格。因此,原始文件中的每两行行号和文本会被合并为一行。
> filename_with_line_numbers.txt
:最后一部分将处理后的结果重定向到一个新文件 filename_with_line_numbers.txt
中,这个文件将包含带有行号的每一行文本。
12. 删除行尾的空白字符:
sed -i 's/[[:space:]]*$//' filename.txt
删除 filename.txt
文件中每一行末尾的空白字符,包括空格和制表符。
's/[[:space:]]*$//'
:这是 sed
的编辑命令部分。在单引号内部,s/
开始替换操作,[[:space:]]*
是一个正则表达式,匹配零个或多个空白字符(空格或制表符),$
表示行尾。因此,这个命令会将每一行末尾的空白字符替换为空字符串。
13. 批量重命名文件:
ls | sed 's/\(.*\).txt/mv & \1.dat/' | sh
将当前目录下所有以 .txt
结尾的文件批量重命名为以 .dat
结尾
ls
:列出当前目录下的所有文件。
|
:管道符号,将 ls
命令的输出传递给下一个命令。
sed 's/\(.*\).txt/mv & \1.dat/'
:这个 sed
命令用于替换文件名。其中:
s/
开始替换操作。
\(.*\).txt:
匹配以 .txt
结尾的文件名,并捕获文件名的部分。
mv & \1.dat:
替换为 mv
命令,其中 &
表示匹配到的整个字符串(即原始文件名),\1
表示捕获的文件名部分,然后将 .txt
后缀替换为 .dat
后缀。
|
:再次使用管道符号,将 sed
的输出传递给下一个命令。
sh
:表示将传递给它的命令作为 shell 脚本执行。
14. 注释所有行:
sed -i.bak 's/^/#/' test.conf
's/^/#/'
:这是 sed
的编辑命令部分。在单引号内部,s/^/#/
表示将每一行的行首 (^
) 替换为 #
注释符。
15. 取消注释所有行:
sed -i '0,/^\s*#/s///' test.conf
删除第一个出现的以 #
开头的注释行(包括行首可能存在的空白字符)。
'0,/^\s*#/s///'
:这是 sed
的编辑命令部分。在单引号内部,0,/^\s*#/
表示从文件开头到第一个匹配 ^\s*#
的行(即以零个或多个空白字符开头后紧跟 #
的行),s///
表示将匹配到的内容替换为空字符串。
3. 实际应用
删除配置文件中所有的注释行
sed的一大妙用就是删除配置文件中所有带有#注释的行,以获得一个“干净的配置文件”
删除以#开头的注释行:
sed -i.bak '/^\s*#/d' test.conf
-i.bak
:-i
参数表示直接在原始文件上进行编辑,并且指定备份文件的后缀为 .bak
。这意味着原始文件会被编辑,而且会在同级目录下生成一个备份文件,其文件名为原始文件名加上 .bak
后缀。
'/^\s*#/d'
:这是 sed
的编辑命令部分。在单引号内部,/^\s*#/d
使用正则表达式匹配所有以 #
开头的行,并将其删除。^
表示行首,\s*
匹配零个或多个空白字符。
test.conf
:要操作的文件名。
删除以#开头的注释行或者行尾的注释:
sed -i.bak '/^\s*#/d; s/\s*#.*$//' test.conf
-i.bak
:-i
参数表示直接在原始文件上进行编辑,并且指定备份文件的后缀为 .bak
。这意味着原始文件会被编辑,而且会在同级目录下生成一个备份文件,其文件名为原始文件名加上 .bak
后缀。
'/^\s*#/d; s/\s*#.*$//'
:这是 sed
的编辑命令部分。在单引号内部,/^\s*#/d
使用正则表达式匹配所有以 #
开头的行,并将其删除。;
表示分隔符,表示同时执行多个编辑操作。s/\s*#.*$//
用于删除行内从 #
开始到行尾的内容。\s*
匹配零个或多个空白字符,.*
匹配任意字符(除换行符外)的零个或多个重复,$
表示行尾。
test.conf
:要操作的文件名。
快速还原上面修改后的配置文件
如果你觉得删除注释后不便于维护,可以使用下面的命令快速还原(同样适用于所有sed命令备份后的还原):
\cp test.conf{.bak,}
\cp
:这是使用 \
转义的 cp
命令,它会覆盖可能已存在的别名,确保使用的是系统的 cp
命令而不是可能存在的别名或函数。 -- 覆盖系统默认的alias cp='cp -i', -i: 会提示是否覆盖的交互
test.conf{.bak,}
:这是 Bash 的花括号展开(Brace Expansion)语法。{}
中的内容会被展开成两个字符串,分别是 test.conf.bak
和 test.conf
。这意味着 cp
命令会将 test.conf.bak
复制为 test.conf
。