目录
1. 将模式空间的内容复制到保持空间
2. 模式空间到保持空间的逐行复制隔行匹配
sed 有两个内置的存储空间:
- 模式空间:该空间是 sed 内置的一个缓冲区,是 sed 执行的正常流程中,暂存当前处理行的空间。每处理完一行都会清空模式空间再读取下一行。模式空间初始为空。
- 保持空间:保持空间是另外一个缓冲区,用来存放临时数据,以便在后续处理中使用。与模式空间不同,保持空间的内容不会在循环中被删除。不能在保持空间上执行普通的 sed 命令。保持空间初始为一个换行符。
命令 h(hold)把模式空间的内容复制到保持空间,和命令 x 不同,命令 h 不会修改当前模式空间的内容。执行命令 h 时,当前保持空间的内容会被模式空间的内容覆盖。
假定目前模式空间内容为“line 1”,保持空间内容为“line 2”。那么执行命令 h 后,模式空间的内容仍然为“line 1”,保持空间的内容则变为“line 1”。
1. 将模式空间的内容复制到保持空间
#echo "Hello World" | sed 'h; /World/!d; g'
Hello World
#
本例子中 sed 执行以下操作:
- 读取输入行 Hello World 到模式空间。
- 执行 h 命令,模式空间的内容 Hello World 被复制到保持空间。
- 执行模式匹配 /World/!d,如果不是包含 World 的行,则删除模式空间的内容并读取下一行。由于这里是匹配到了,所以不删除模式空间的内容。
- 执行 g 命令,将保持空间(现在是 Hello World)的内容复制回模式空间,覆盖原有内容。
最终输出不变,仍然是 Hello World。
2. 模式空间到保持空间的逐行复制隔行匹配
示例文本 empnametitle.txt 的内容如下:
John Doe
CEO
Jason Smith
IT Manager
Raj Reddy
Sysadmin
Anand Ram
Developer
Jane Miller
Sales Manager
在这个文件中,每个员工的姓名和职位位于连续的两行内。下面的命令打印职位是 Manager 的员工名。
#sed -n -e '/Manager/!h' -e '/Manager/{x;p}' empnametitle.txt
Jason Smith
Jane Miller
#
这个例子中:
- /Manager/!h 是将模式空间中不包含关键字 Manager 的内容复制到保持空间。这样保持空间的内容可能会是雇员名称或职位,但不是 Manager。本例没有使用命令 n 来获取下一行,而是通过正常的流程来读取后续内容。
- /Manager/{x;p} 的作用是如果模式空间内容包含关键字 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 Jason Smith 空 | Jason Smith IT Manager IT Manager | x => p Jason Smith => |
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 Jane Miller | Jane Miller Sales Manager | x => p Jane Miller |