使用sed 大致有两种方法:
- 在模式空间中保留多行;或
- 将上一行保留在保留空间中。
只使用模式空间意味着一个非常简洁的版本:
sed 'N; s/,\n*)/)/; P; D'
这依赖于模式空间能够容纳多行,并且能够将换行符与\n 匹配。并非所有版本的 sed 都可以做到这一点,但 GNU sed 可以。
这还依赖于 N、P 和 D 的隐式行为,这些行为会根据何时到达输入结束而变化。阅读man sed了解血腥细节。
展开到每行一个命令得到:
sed '
N
s/,\n*)/)/
P
D
'
如果您只有 POSIX 版本的sed 可用,您还需要使用保留空间。在这种情况下,想法是当您在模式空间中看到 ) 时,您可以编辑保留空间中的行以删除逗号:
sed '1 { h; d; }; /^)/ { x; s/,$//; x; }; x; $ { p; x; s/,$//; }'
展开我们得到:
sed '
1 {
h
d
}
/^)/ {
x
s/,$//
x
}
x
$ {
p
x
s/,$//
}
'
打破它:接下来是一个“sed 脚本”;所以只需在它周围加上 '' 并在它前面加上“sed”:
sed '
首先无条件地将第一行从模式空间复制到保持空间,然后删除模式空间(这会强制跳到下一行)
1 {
h
d
}
对于以 ')' 开头的每一行,交换模式空间和保持空间(因此您现在在模式空间中有前一行),删除尾随逗号(如果有),然后再次交换回来:
/^)/ {
x
s/,$//
x
}
现在将模式空间与保持空间交换,以便保持空间现在保持当前行,而模式空间保持上一行。
x
通常,当到达脚本末尾时,模式空间的内容将被发送到输出,但我们首先要处理另一种情况。
在最后一行,打印上一行,然后交换以检索最后一行,然后(因为我们到达 script0 的末尾也打印它。此代码还将从最后一行删除尾随逗号,但这是可选;如果您不想要,可以将其删除。
$ {
p
x
s/,$//
}
到达 sed 脚本的末尾时,将打印模式空间;所以最后没有“p”。
如前所述,从头开始关闭引用。
'
注意:
如果您需要向前扫描多行,而不是“x”来交换一行,使用“H;g”附加到保留空间,然后将保留空间复制到模式空间,然后“P;D”打印并删除到第一个换行符。 (H、P 和 D 是 GNU 扩展。)