# "D"命令的大致循环结构
for ((line=1;line<=last_line_num;++line))
do
read $line to pattern_space;
while pattern_space is not null
do
execute cmd1 in SCRIPT;
execute cmd2 in SCRIPT;
ADDR1,ADDR2{ # "D" command
delete first line in pattern_space;
continue;
};
……
auto_print;
remove_pattern_space;
done
done
# "P"命令的大致循环结构
for ((line=1;line<=last_line_num;++line))
do
read $line to pattern_space;
while pattern_space is not null
do
execute cmd1 in SCRIPT;
execute cmd2 in SCRIPT;
ADDR1,ADDR2{ # "P" command
print first line in pattern_space;
};
……
auto_print;
remove_pattern_space;
done
done
(10).buffer空间数据交换命令"h"、"H"、"g"、"G"、"x"简单说明。
sed除了维护模式空间(pattern space),还维护另一个buffer空间:保持空间(hold space)。这两个空间初始状态都是空的。
绝大多数时候,sed仅依靠模式空间就能达到目的,但有些复杂的数据操作则只能借助保持空间来实现。之所以称之为保持空间,是因为它是暂存数据用的,除了仅有的这几个命令外,没有任何其他命令可以操作该空间,因此借助它能实现数据的持久性。
保持空间的作用很大,它和模式空间之间的数据交换能实现很多看上去不能实现的功能,是实现sed高级功能所必须的,例如"窗口滑动"。同样,这不是本文的内容。所以只简单解释这几个命令的作用:
"h"命令:将当前模式空间中的内容覆盖到保持空间。
"H"命令:在保持空间的尾部加上一个换行符"\n",并将当前模式空间的内容追加到保持空间的尾部。
"g"命令:将保持空间的内容覆盖到当前模式空间。
"G"命令:在模式空间的尾部加上一个换行符"\n",并将当前保持空间的内容追加到模式空间的尾部。
"x"命令:交换模式空间和保持空间的内容。
注意,无论是交换、追加还是覆盖,原空间的内容都不会被删除。
总结看到这里,对sed已经有了一些概念,也许已经发现了sed的重点在于各选项和各命令是如何影响sed循环以及SCRIPT循环的。确实如此,在info sed文档中,虽然没有将这些工作机制详细描述,但各选项各命令说明中,在需要的时候都提到了这些细节,而我所做的只不过是将其系统性地描述出来、做一些深入,再给几个示例解释,并使用通俗易懂的循环结构来展示这些机制。
最后,验证前文"n"和"N"命令留下的疑问:"n"和"N"命令是先判断是否还有下一行,再自动输出的。也就是证明下面两个判断语句采用前者还是后者的问题。
ADDR1,ADDR2{ # "n" command
if [ "$line" -ne "$last_line_num" ];then
auto_print;
remove_pattern_space;
read next_line to pattern_space;
else
auto_print;
remove_pattern_space;
exit;
fi
};
ADDR1,ADDR2{ # "n" command
auto_print;
remove_pattern_space;
[ "$line" -ne "$last_line_num" ] && read next_line to pattern_space || exit;
};