使用 sed 处理文本文件(Using sed to process text files)

前言

sed 是一款 GNU 流编辑器,可以按照指定的规则去处理文本文件或流,其强大的功能使用户在命令中快捷地修改文本文件成为可能。

它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。

sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:

首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行,先将处理得到的结果保存到一个暂存缓冲区中(也称为保存空间),再将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。

安装

Linux(Ubuntu) 系统已经自带,mac OS系统也默认安装,Windows 需要安装一个名为 的软件,安装过程暂略。

msys2

使用

摘要

sed [选项] [选项参数] [脚本] [输入文件] [其他参数]

基本选项及其参数

短选项 功能 对应长选项
-n 取消默认输出 –quiet, –silent
-e 脚本 添加脚本至要运行的命令 –expression=脚本
-f 脚本文件 添加脚本文件的内容到要运行的命令 –file=脚本文件
-i [后缀] 编辑已存在的文件。如果提供了后缀则生成指定后缀的备份文件 –in-place[=后缀]
-E, -r 在脚本中使用扩展的正则表达式 –regexp-extended

脚本

格式

[addr1[,addr2]][!]{命令}

地址

  • 脚本中可以不指定地址,这样命令将会为输入的所有行执行
  • 如果脚本给出了1个地址,那么命令将只会为匹配此地址上的行执行(单地址类型)
  • 如果脚本给出了2个地址,那么命令将会对从匹配的第一个地址到第二个地址的区域的所有输入行执行 (双地址类型)
  • 命令前的 ! 会使命令在指定地址或地址范围以外的区域执行

地址类型

  • 单地址类型

    类型描述
    类型含义

    number (数字)
    只匹配行号为 number 的行

    first~step (eg:1~2)
    匹配每一个第 step 行并从 first 开始计数

    $
    只匹配最后一行

    /regexp/
    匹配符合正则表达式 regexp 的行

    \aregexpb
    匹配符合正则表达式 regexp 的行,其中的a、b为任意字符,用于辅助定位

类型描述 类型含义
number (数字) 只匹配行号为 number 的行
first~step (eg:1~2) 匹配每一个第 step 行并从 first 开始计数
$ 只匹配最后一行
/regexp/ 匹配符合正则表达式 regexp 的行
\aregexpb 匹配符合正则表达式 regexp 的行,其中的a、b为任意字符,用于辅助定位
regexp
regexp
regexp 
  • 双地址类型

    类型描述
    类型含义

    p,q (数字)
    匹配从第 p 行开始到第 q 行的范围

    p,+N (数字)
    匹配从第 p 行开始到其之后的 N 行

    p,~N (数字)
    匹配第 p 行和从第 p 行开始每隔 N 行后的下一行

    p, /regexp/ (p为数字,regexp为正则表达式)
    匹配从第 p 行开始,直到首次发现符合正则表达式regexp的行(不含第 p 行,见注1)

类型描述 类型含义
p,q (数字) 匹配从第 p 行开始到第 q 行的范围
p,+N (数字) 匹配从第 p 行开始到其之后的 N 行
p,~N (数字) 匹配第 p 行和从第 p 行开始每隔 N 行后的下一行
p, /regexp/ (p为数字,regexp为正则表达式) 匹配从第 p 行开始,直到首次发现符合正则表达式regexp的行(不含第 p 行,见注1)

注1:

  • 若 p 为 0,则含义为 匹配从文件首字符开始,直到首次发现符合正则表达式regexp的行
  • 若 p 为 大于 0 的行号,则 regexp 不会对第 p 行进行测试

命令

命令描述 命令含义
a \ text 在匹配的行后追加文本text
i \ text 在匹配的行前插入文本text
c \ text 用文本text替换匹配行或范围
d 删除匹配行或范围
p 输出匹配行或范围
s/regexp/replacement/[替换标记] 在匹配行或范围内,用 replacement 替换使用正则 regexp 匹配到的内容
regexp

注2:追加 / 插入 / 替换多行时,要在 text 内部需换行的位置用反斜杠续行。

替换标记

标记描述 标记含义
g 行内全面替换
Ng 行内从第N处匹配开始替换
\1…\9 子串匹配(?)

正则表达式元字符集

由于脚本中的命令支持正则表达式,在这就不得不提一下正则表达式的元字符集,不同的元字符在正则表达式中可以覆盖不同的匹配场景。

字符 行为描述 示例
^ 行首匹配 /^sed/匹配所有以sed开头的行
$ 行尾匹配 /sed$/匹配所有以sed结尾的行
. 非换行符单个匹配 /s.d/匹配s后接一个任意字符,最后是d
* 0至多个字符匹配 /*sed/匹配一个或多个空格后紧跟sed的行; /sed*/匹配se后紧跟0至多个d的行
[] 字符组内单个匹配 /[sS]ed/匹配sed和Sed
[^] 字符组外单个匹配 /[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行
\(..\) 匹配子串,以在之后使用 s/\(love\)able/\1rs,loveable被替换成lovers,见注3
& 匹配搜索串,以在之后使用 s/love/ **&**/,love被替换成 **love**
\< 匹配单词的开始 /\<sed/匹配包含以sed开头的单词的行
\> 匹配单词的结束 /sed\>/匹配包含以sed结尾的单词的行
x\{m\} 匹配字符x,m次 /d\{5\}/ 匹配含连续5个d的行
x\{m,\} 匹配字符x,至少m次 /d\{5,\}/ 匹配至少含连续5个d的行
x\{m,n\} 匹配字符x,至少m次,至多n次 /d\{5,9}/ 匹配含连续5到9个d的行
/^sed/
/sed$/
/s.d/
/*sed/
/sed*/
/[sS]ed/
/\<sed/
/sed\>/
/d\{5\}/
/d\{5,\}/
/d\{5,9}/

范例

  • 注释掉 build.gradle 中 implementation ‘org.greenrobot:greendao:3.3.0
# 在含有 org.greenrobot:greendao:3.3.0 的行上进行替换,替换i为 //i
sed '/org.greenrobot:greendao:3.3.0/s/i/\/\/i/' build.gradle 
# 替换 implementation 'org.greenrobot:greendao:3.3.0 为 在其之前加上//
sed "s/implementation 'org.greenrobot:greendao:3.3.0'/\/\/&/" build.gradle

说明

  • 当命令的匹配模式有单引号’ ‘时,使用双引号” “包围命令。其他情况下可使用单引号包围命令。
  • 当命令的匹配模式或要替换的文本有斜线/时,需在前追加反斜线\/方可正常使用。
————————

preface

Sed is a GNU stream editor, which can process text files or streams according to the specified rules. Its powerful function makes it possible for users to quickly modify text files in commands.

It does not modify the file unless you use shell redirection to save the results. By default, all output lines are printed on the screen.

The SED editor processes the file (or input) line by line and sends the results to the screen. The specific process is as follows:

First sed saves the row currently being processed in a temporary buffer (also known as < strong > mode space < / strong >), then processes the row in the temporary buffer, and sends the row to the screen after completion. Sed saves the processing result to a temporary buffer (also known as < strong > save space < / strong >) after processing each line, and then deletes it from the temporary buffer, and then reads the next line in for processing and display. After processing the last line of the input file, sed ends running. Sed saves each line in a temporary buffer and edits the copy, so the original file will not be modified.

install

Linux (Ubuntu) system comes with it, and Mac OS system is installed by default. Windows needs to install a software named. The installation process is omitted.

msys2

use

abstract

sed [选项] [选项参数] [脚本] [输入文件] [其他参数]

Basic options and their parameters

短选项 功能 对应长选项
-n 取消默认输出 –quiet, –silent
-e 脚本 添加脚本至要运行的命令 –expression=脚本
-f 脚本文件 添加脚本文件的内容到要运行的命令 –file=脚本文件
-i [后缀] 编辑已存在的文件。如果提供了后缀则生成指定后缀的备份文件 –in-place[=后缀]
-E, -r 在脚本中使用扩展的正则表达式 –regexp-extended

script

format

[addr1[,addr2]][!]{命令}

address

  • No address can be specified in the script, so the command will be executed for all lines entered
  • If the script gives an address, the command will only be executed for lines that match this address (single address type)
  • If the script gives 2 addresses, the command will execute on all input lines from the matching first address to the second address (double address type)
  • Before the order! Causes the command to be executed outside the specified address or address range

Address type

  • Single address type
    Type description
    Type meaning
    Number
    Match only rows with row number
    first~step (eg:1~2)
    Match each step line and count from first
    $
    Match only the last line
    /regexp/
    Match rows that match the regular expression regexp
    \aregexpb
    Match the line that conforms to the regular expression regexp, where a and B are arbitrary characters for auxiliary positioning
类型描述 类型含义
number (数字) 只匹配行号为 number 的行
first~step (eg:1~2) 匹配每一个第 step 行并从 first 开始计数
$ 只匹配最后一行
/regexp/ 匹配符合正则表达式 regexp 的行
\aregexpb 匹配符合正则表达式 regexp 的行,其中的a、b为任意字符,用于辅助定位
regexp
regexp
regexp 
  • Dual address type
    Type description
    Type meaning
    p. Q (number)
    Match the range from line p to line Q
    p. + n (number)
    Match the N lines starting from line P and following it
    p. ~ n (number)
    Match line P and the next line after every n lines starting from line P
    p. / regexp / (P is a number, regexp is a regular expression)
    If the regular expression does not match P for the first time, see line exp
类型描述 类型含义
p,q (数字) 匹配从第 p 行开始到第 q 行的范围
p,+N (数字) 匹配从第 p 行开始到其之后的 N 行
p,~N (数字) 匹配第 p 行和从第 p 行开始每隔 N 行后的下一行
p, /regexp/ (p为数字,regexp为正则表达式) 匹配从第 p 行开始,直到首次发现符合正则表达式regexp的行(不含第 p 行,见注1)

Note 1:

  • If P is 0, it means that the matching starts from the first character of the file until the line conforming to the regular expression regexp is found for the first time
  • If P is a line number greater than 0, regexp will not test line P

command

命令描述 命令含义
a \ text 在匹配的行后追加文本text
i \ text 在匹配的行前插入文本text
c \ text 用文本text替换匹配行或范围
d 删除匹配行或范围
p 输出匹配行或范围
s/regexp/replacement/[替换标记] 在匹配行或范围内,用 replacement 替换使用正则 regexp 匹配到的内容
regexp

Note 2: when adding / inserting / replacing multiple lines, use the backslash < / strong > to continue the line where the < strong > line feed is required in the text.

Replace tag

标记描述 标记含义
g 行内全面替换
Ng 行内从第N处匹配开始替换
\1…\9 子串匹配(?)

Regular expression metacharacter set

Since the commands in the script support < strong > regular expressions < / strong >, we have to mention the < strong > metacharacter < / strong > set of regular expressions. Different metacharacters can cover different matching scenarios in regular expressions.

字符 行为描述 示例
^ 行首匹配 /^sed/匹配所有以sed开头的行
$ 行尾匹配 /sed$/匹配所有以sed结尾的行
. 非换行符单个匹配 /s.d/匹配s后接一个任意字符,最后是d
* 0至多个字符匹配 /*sed/匹配一个或多个空格后紧跟sed的行; /sed*/匹配se后紧跟0至多个d的行
[] 字符组内单个匹配 /[sS]ed/匹配sed和Sed
[^] 字符组外单个匹配 /[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行
\(..\) 匹配子串,以在之后使用 s/\(love\)able/\1rs,loveable被替换成lovers,见注3
& 匹配搜索串,以在之后使用 s/love/ **&**/,love被替换成 **love**
\< 匹配单词的开始 /\<sed/匹配包含以sed开头的单词的行
\> 匹配单词的结束 /sed\>/匹配包含以sed结尾的单词的行
x\{m\} 匹配字符x,m次 /d\{5\}/ 匹配含连续5个d的行
x\{m,\} 匹配字符x,至少m次 /d\{5,\}/ 匹配至少含连续5个d的行
x\{m,n\} 匹配字符x,至少m次,至多n次 /d\{5,9}/ 匹配含连续5到9个d的行
/^sed/
/sed$/
/s.d/
/*sed/
/sed*/
/[sS]ed/
/\<sed/
/sed\>/
/d\{5\}/
/d\{5,\}/
/d\{5,9}/

example

  • 注释掉 build.gradle 中 implementation ‘org.greenrobot:greendao:3.3.0
# 在含有 org.greenrobot:greendao:3.3.0 的行上进行替换,替换i为 //i
sed '/org.greenrobot:greendao:3.3.0/s/i/\/\/i/' build.gradle 
# 替换 implementation 'org.greenrobot:greendao:3.3.0 为 在其之前加上//
sed "s/implementation 'org.greenrobot:greendao:3.3.0'/\/\/&/" build.gradle

explain

  • When the matching pattern of the command has single quotation marks’ ‘, use double quotation marks” to surround the command. In other cases, you can use single quotation marks to enclose commands.
  • When the matching pattern of the command or the text to be replaced has slashes / slashes, you need to add a backslash \ / before it can be used normally.