The Sed exchange command
作为第一个示例,我们可使用交换命令去反序输出一个输入文件的前两行:
cat -n inputfile | sed -n -e 'x;n;p;x;p;q'
当然,在你设置保持空间之后你并没有立即使用它的内容,因为只要你没有显式地去修改它,保持空间中的内容就保持不变。在下面的例子中,我在输入一个文件的前五行后,使用它去删除第一行:
保持命令cat -n inputfile | sed -n -e '
1{x;n} # 交换保持和模式空间
# 保存第 1 行到保持空间中
# 然后读取第 2 行
5{
p # 输出第 5 行
x # 交换保持和模式空间
# 去取得第 1 行的内容放回到模式空间
}
1,5p # 输出第 2 到第 5 行
# (并没有输错!尝试找出这个规则
# 没有在第 1 行上运行的原因 ;)
'
保持命令(h)是用于将模式空间中的内容保存到保持空间中。但是,与交换命令不同的是,模式空间中的内容不会被改变。保持命令有两种用法:
- h 将复制模式空间中的内容到保持空间中,覆盖保持空间中任何已经存在的内容。
- H 将模式空间中的内容追加到保持空间中,使用一个新行作为分隔符。
The Sed hold command
上面使用交换命令的例子可以使用保持命令重写如下:
获取命令cat -n inputfile | sed -n -e '
1{h;n} # 保存第 1 行的内容到保持缓冲区并继续
5{ # 在第 5 行
x # 交换模式和保持空间
# (现在模式空间包含了第 1 行)
H # 在保持空间的第 5 行后追加第 1 行
x # 再次交换第 5 行和第 1 行,第 5 行回到模式空间
}
1,5p # 输出第 2 行到第 5 行
# (没有输错!尝试去找到为什么这个规则
# 不在第 1 行上运行 ;)
'
获取命令(g)与保持命令恰好相反:它从保持空间中取得内容并将它置入到模式空间中。同样它也有两种方式:
- g 将复制保持空间中的内容并将其放入到模式空间,覆盖模式空间中已存在的任何内容
- G 将保持空间中的内容追加到模式空间中,并使用一个新行作为分隔符
The Sed get command
将保持命令和获取命令一起使用,可以允许你去存储并调回数据。作为一个小挑战,我让你重写前一节中的示例,将输入文件的第 1 行放置在第 5 行之后,但是这次必须使用获取和保持命令(使用大写或小写命令的版本)而不能使用交换命令。带点小运气,可以更简单!
同时,我可以给你展示另一个示例,它能给你一些灵感。目标是将拥有登录 shell 权限的用户与其它用户分开:
复习打印、删除和次行命令cat -n inputfile | sed -En -e '
\=(/usr/sbin/nologin|/bin/false)$= { H;d; }
# 追回匹配的行到保持空间
# 然后继续下一个循环
p # 输出其它行
$ { g;p } # 在最后一行上
# 获取并打印保持空间中的内容
'
现在你已经更熟悉使用保持空间了,我们回到打印、删除和次行命令。我们已经讨论了小写的 p、d 和 n 命令了。而它们也有大写的版本。因为每个命令都有大小写版本,似乎是 Sed 的习惯,这些命令的大写版本将与多行缓冲区有关:
- P 将模式空间中第一个新行之前的内容输出
- D 删除模式空间中第一个新行之前的内容(包含新行),然后不读取任何新的输入而是使用剩余的文本去重启一个循环
- N 读取输入并追加一个新行到模式空间,用一个新行作为新旧数据的分隔符。继续运行当前的循环。
The Sed uppercase `Delete` command