sed 有两个内置的存储空间:
大写 H 命令表示把模式空间的内容追加到保持空间,追加不会覆盖保持空间的内容。当向初始保持空间追加内容时,因为保持空间初始内容为一个换行符 \n,所以直接把模式空间内容追加进来。当保持空间已经有内容时,H 命令在当前保持空间内容后面加上换行符 \n,然后再把模式空间内容追加进来。
假定目前模式空间内容为“line 1”,保持空间内容为“line 2”。那么执行命令 H 后,模式空间的内容没有改变,仍然为“line 1”,保持空间的内容则变为“line2\nline 1”。
以下是一些使用 H 命令的例子。
#echo "Hello World" | sed -n 'H; x; p;'
Hello World
#
这个 sed 脚本会将模式空间的内容追加到保持空间,然后交换模式空间和保持空间的内容,使得保持空间的内容被打印出来。从输出可以看到比原始文本多了第一行的空行(保持空间的初始换行符)。
#echo -e "Hello\nWorld" | sed -n 'H; x; $!d; x; p'
World
#
这个 sed 脚本会在追加文本到保持空间的同时追加一个换行符。完整的执行流程如下表所示。
循环次数 | 模式空间 | 保持空间 | 操作 |
---|---|---|---|
1 | Hello Hello \nHello 空 | \n \nHello Hello Hello | H => x => d => |
2 | World World Hello\nWorld World | Hello Hello\nWorld World Hello\nWorld | H => x => x => p World |
注意,第一行的 $!d 命令会清空模式空间,并启动下一个循环,这实际上会导致跳过其后的 x; p 命令,直到最后一行。
示例文本 empnametitle.txt 的内容如下:
John Doe
CEO
Jason Smith
IT Manager
Raj Reddy
Sysadmin
Anand Ram
Developer
Jane Miller
Sales Manager
在这个文件中,每个员工的姓名和职位位于连续的两行内。下面的命令在不同行上分别打印管理者的名称和职位。
#sed -n -e '/Manager/!h' -e '/Manager/{H;x;p}' empnametitle.txt
Jason Smith
IT Manager
Jane Miller
Sales Manager
#
这个例子中:
完整的执行流程如下表所示。
循环次数 | 模式空间 | 保持空间 | 操作 |
---|---|---|---|
1 | John Doe John Doe 空 | \n John Doe John Doe | h => |
2 | CEO CEO 空 | John Doe CEO CEO | h => |
3 | Jason Smith Jason Smith 空 | CEO Jason Smith Jason Smith | h => |
4 | IT Manager IT Manager Jason Smith\nIT Manager 空 | Jason Smith Jason Smith\nIT Manager IT Manager IT Manager | H => x => p Jason Smith\nIT Manager => |
5 | Raj Reddy Raj Reddy 空 | IT Manager Raj Reddy Raj Reddy | h => |
6 | Sysadmin Sysadmin 空 | Raj Reddy Sysadmin Sysadmin | h => |
7 | Anand Ram Anand Ram 空 | Sysadmin Anand Ram Anand Ram | h => |
8 | Developer Developer 空 | Anand Ram Developer Developer | h => |
9 | Jane Miller Jane Miller 空 | Developer Jane Miller Jane Miller | h => |
10 | Sales Manager Sales Manager Jane Miller\n Sales Manager | Jane Miller Jane Miller \nSales Manager Sales Manager | H => x => p Jane Miller\n Sales Manager |
也可以把命令保存到 sed 脚本中执行:
创建内容如下的脚本文件 H-upper.sed
#!/bin/sed -nf
/Manager/!h
/Manager/{H;x;p}
修改脚本文件的模式为可执行
chmod u+x H-upper.sed
执行脚本
#./H-upper.sed empnametitle.txt
Jason Smith
IT Manager
Jane Miller
Sales Manager
#
如果想把雇员名称和职位显示在同一行,并以冒号分开,那么只需稍微修改一下即可:
#sed -n -e '/Manager/!h' -e '/Manager/{H;x;s/\n/:/g;p}' empnametitle.txt
Jason Smith:IT Manager
Jane Miller:Sales Manager
#
这个例子除了在第二个 -e 后面的命令中加入了替换命令之外,和前面的例子一样。H、x 和 p 都完成和之前相同的操作。在交换模式空间和保持空间之后,命令 s 把换行符 \n 替换为分冒号,然后打印出来。
同样可以把上面命令保存到 sed 脚本中执行:
创建内容如下的脚本文件 H1-upper.sed
#!/bin/sed -nf
/Manager/!h
/Manager/{H;x;s/\n/:/g;p}
修改脚本文件的模式为可执行
chmod u+x H1-upper.sed
执行脚本
#./H1-upper.sed empnametitle.txt
Jason Smith:IT Manager
Jane Miller:Sales Manager
#