Linux shell 之 sed 命令详解 第三部分
目录:
五、修改行
六、转换命令
七、回顾打印
八、使用 sed 处理文件
五、修改行
修改( change)命令允许修改数据流中整行文本的内容。它跟插入和附加命令的工作机制一样,你必须在sed命令中单独指定新行。
1 sed '3c
2 > This is a changed line of text.' data4.txt
3 This is line number 1
4 This is line number 2
5 This is a changed line of text.
6 This is line number 4
7 This is line number 5
8 $
在这个例子中,sed 编辑器会修改第三行中的文本。也可以用文本模式来寻址。
1 $ sed '/number 3/c
2 > This is a changed line of text.' data4.txt
3 This is line number 1
4 This is line number 2
5 This is a changed line of text.
6 This is line number 4
7 This is line number 5
8 $
文本模式修改命令会修改它匹配的数据流中的任意文本行。
1 $ sed '/number 1/c
2 > This is a changed line of text.' data5.txt
3 This is a changed line of text.
4 This is line number 2.
5 This is line number 3.
6 This is line number 4.
7 This is line number 5.
8 This is line number 6.
9 This is a changed line of text.
10 This is text you want to keep.
11 This is the last line in the file.
12 $
你可以在修改命令中使用地址区间,但结果未必如愿。
1 $ sed '2,3c
2 > This is a new line of text.' data5.txt
3 This is line number 1.
4 This is a new line of text.
5 This is line number 4.
6 This is line number 5.
7 This is line number 6.
8 This is line number 1 again.
9 This is text you want to keep.
10 This is the last line in the file.
11 $
sed 编辑器会用这一行文本来替换数据流中的两行文本,而不是逐一修改这两行文本。
六、转换命令
转换(transform)命令(y)是唯一可以处理单个字符的 sed 编辑器命令。转换命令格式如下。
[address]y/inchars/outchars/
转换命令会对 inchars 和 outchars 值进行一对一的映射。inchars 中的第一个字符会被转换位 outchars 中的第一个字符,第二个字符会被转换成 outchars 中的第二个字符。这个映射过程会一直持续到处理完指定字符。如果 inchars 和 ouchars 的长度不同,则 sed 编辑器会产生一条错误消息。
1 $ sed 'y/123/789/' data5.txt
2 This is line number 7.
3 This is line number 8.
4 This is line number 9.
5 This is line number 4.
6 This is line number 5.
7 This is line number 6.
8 This is line number 7 again.
9 This is text you want to keep.
10 This is the last line in the file.
11 $
如你在输出中看到的,inchars 模式中指定字符的每个实例都会被替换成 outchars 模式中相同位置的那个字符。
转换命令是一个全局命令,也就是说,它会在文本行中找到的所有指定字符自动进行转换,而不会考虑它们出现的位置。
1 $ echo "This 1 is a test of 1 try." | sed 'y/123/456/'
2 This 4 is a test of 4 try.
3 $
sed 编辑器转换了在文本行中匹配到的字符 1 的两个实例。你无法限定只转换在特定地方出现的字符。
七、回顾打印
前面写过使用 p 标记和替换命令显示 sed 编辑器修改过的行。另外有 3 个命令也能用来打印数据流中的信息:
⭐ p 命令用来打印文本行;
⭐ 等号( =)命令用来打印行号;
⭐ l(小写的L)命令用来列出行。
1、打印行
跟替换命令中的 p 标记类似, p 命令可以打印 sed 编辑器输出中的一行。如果只用这个命令,也没什么特别的。
1 echo 'this is a test' | sed 'p'
2 this is a test
3 this is a test
4 $
它所做的就是打印已有的数据文本。打印命令最常见的用法是打印包含匹配文本模式的行。
1 $ cat data4.txt
2 This is line number 1
3 This is line number 2
4 This is line number 3
5 This is line number 4
6 This is line number 5
7 $
8 $ sed -n '/number 3/p' data4.txt
9 This is line number 3
10 $
在命令行上用-n选项,你可以禁止输出其他行,只打印包含匹配文本模式的行。
也可以用它来快速打印数据流中的某些行。
1 $ sed -n '2,3p' data4.txt
2 This is line number 2
3 This is line number 3
4 $
如果需要在修改之前查看行,也可以使用打印命令,比如与替换或修改命令一起使用。可以创建一个脚本在修改行之前显示该行。
1 $ sed -n '/3/{
2 > p
3 > s/line/tag/p
4 > }' data4.txt
5 This is line number 3
6 This is tag number 3
7 $
8 $
9 $
10 $
11 $ sed -n '3{
12 p
13 s/line/tag/p
14 }' data4.txt
15 This is line number 3
16 This is tag number 3
17 $
sed 编辑器命令会查找包含数字3的行,然后执行两条命令。首先,脚本用 p 命令来打印出原始行;然后它用 s 命令替换文本,并用 p 标记打印出替换结果。输出同时显示了原来的行文本和新的行文本。
2、打印行号
等号命令会打印行在数据流中的当前行号。行号由数据流中的换行符决定。每次数据流中出现一个换行符, sed 编辑器会认为一行文本结束了。
1 $ cat data1.txt
2 the quick brown fox jumps over the lazy dog.
3 The quick brown fox jumps over the lazy dog.
4 The quick brown fox jumps over the lazy dog.
5 The quick brown fox jumps over the lazy dog.
6 $
7 zhengchuanyu@zhengchuanyu:~/reverse_xiaoyu$ sed '=' data1.txt
8 1
9 the quick brown fox jumps over the lazy dog.
10 2
11 The quick brown fox jumps over the lazy dog.
12 3
13 The quick brown fox jumps over the lazy dog.
14 4
15 The quick brown fox jumps over the lazy dog.
16 $
sed 编辑器在实际的文本行出现前打印了行号。如果你要在数据流中查找特定文本模式的话,等号命令用起来非常方便。
1 $ sed -n '/number 4/{
2 > =
3 > p
4 > }' data4.txt
5 4
6 This is line number 4
7 $
利用 -n 选项,你就能让 sed 编辑器只显示包含匹配文本模式的行的行号和文本。
3、列出行
列出( list)命令( l)可以打印数据流中的文本和不可打印的 ASCII 字符。任何不可打印字符要么在其八进制值前加一个反斜线,要么使用标准C风格的命名法(用于常见的不可打印字符),比如 ,来代表制表符。
1 $ cat data4.txt
2 This is line number 1
3 This is line number 2
4 This is line number 3
5 This is line number 4
6 This is line number 5
7 $
8 $ sed -n 'l' data4.txt
9 This is line number 1$
10 This is line number 2$
11 This is line number 3$
12 This is line number 4$
13 This is line number 5$
14 $
1 $ cat data6.txt
2 I love linux shell
3 $
4 $ sed -n 'l' data6.txt
5 I love linux shell$
6 $
制表符的位置使用 来显示。行尾的美元符表示换行符。如果数据流包含了转义字符,列出命令会在必要时候用八进制码来显示。
1 $ cat data10.txt
2 This line contains an escape character.
3 $
4 $ sed -n 'l' data10.txt
5 This line contains an escape character. a$
6 $
data10.txt 文本文件包含了一个转义控制码来产生铃声。当用 cat 命令来显示文本文件时,你看不到转义控制码,只能听到声音(如果你的音箱打开的话)。但是,利用列出命令,你就能显示出所使用的转义控制码。
八、使用 sed 处理文件
替换命令包含一些可以用于文件的标记。还有一些 sed 编辑器命令也可以实现同样的目标,不需要非得替换文本。
1、写入文件
w 命令用来向文件写入行。该命令的格式如下:
[address]w filename
filename 可以使用相对路径或绝对路径,但不管是哪种,运行 sed 编辑器的用户都必须有文件的写权限。地址可以是 sed 中支持的任意类型的寻址方式,例如单个行号、文本模式、行区间或文本模式。
下面的例子是将数据流中的前两行打印到一个文本文件中。
1 $ sed '1,2w test.txt' data4.txt
2 This is line number 1
3 This is line number 2
4 This is line number 3
5 This is line number 4
6 This is line number 5
7 $
8 $ cat test.txt
9 This is line number 1
10 This is line number 2
11 $
当然,如果你不想让行显示到 STDOUT 上,你可以用 sed 命令的 -n 选项。
如果要根据一些公用的文本值从主文件中创建一份数据文件,比如下面的邮件列表中的,那么 w 命令会非常好用。
1 $ cat data11.txt
2 Blum, R Browncoat
3 McGuiness, A Alliance
4 Bresnahan, C Browncoat
5 Harken, C Alliance
6 $
7 $ sed -n '/Browncoat/w Browncoats.txt' data11.txt
8 $
9 $ cat Browncoats.txt
10 Blum, R Browncoat
11 Bresnahan, C Browncoat
12 $
sed 编辑器会只将包含文本模式的数据行写入目标文件。
2、从文件读取数据
了解了如何在 sed 命令行上向数据流中插入或附加文本。读取( read)命令( r)允许你将一个独立文件中的数据插入到数据流中。
读取命令的格式如下:
[address]r filename
filename 参数指定了数据文件的绝对路径或相对路径。你在读取命令中使用地址区间,只能指定单独一个行号或文本模式地址。 sed 编辑器会将文件中的文本插入到指定地址后。
1 $ cat data7.txt
2 I love linux shell
3 $ sed '$r data7.txt' data4.txt
4 This is line number 1
5 This is line number 2
6 This is line number 3
7 This is line number 4
8 This is line number 5
9 I love linux shell
10 $
sed 编辑器会将数据文件中的所有文本行都插入到数据流中。同样的方法在使用文本模式地址时也适用。
1 $ sed '/number 2/r data12.txt' data6.txt
2 This is line number 1.
3 This is line number 2.
4 This is an added line.
5 This is the second added line.
6 This is line number 3.
7 This is line number 4.
8 $
如果你要在数据流的末尾添加文本,只需用美元符地址符就行了。
读取命令的另一个很酷的用法是和删除命令配合使用:利用另一个文件中的数据来替换文件中的占位文本。举例来说,假定你有一份套用信件保存在文本文件中:
1 $ cat notice.std
2 Would the following people:
3 LIST
4 please report to the ship's captain.
5 $
套用信件将通用占位文本 LIST 放在人物名单的位置。要在占位文本后插入名单,只需读取命令就行了。但这样的话,占位文本仍然会留在输出中。要删除占位文本的话,你可以用删除命令。结果如下:
1 $ sed '/LIST/{
2 > r data11.txt
3 > d
4 > }' notice.std
5 Would the following people:
6 Blum, R Browncoat
7 McGuiness, A Alliance
8 Bresnahan, C Browncoat
9 Harken, C Alliance
10 please report to the ship's captain.
11 $
现在占位文本已经被替换成了数据文件中的名单。