我有一个数据库日志文件,看起来像这个
tbl
---
tmp1
col1|col2
---------
22| 33
32| 45
tbl
---
tmp2
col1|col2| col3
---------------
22| 33| 123
32| 45| 456
我正在尝试编写一个sed命令,该命令可以查找开始的行带有"---",并在上面两行添加回车符。因此输出看起来像:
tbl
---
tmp1
col1|col2
---------
22| 33
32| 45
tbl
---
tmp2
col1|col2| col3
---------------
22| 33| 123
32| 45| 456
使用sed可以做到这一点吗?如果是,怎么办?
方法1
按照Sundeep的建议,使用tac
反转输入使这个问题变得容易得多:
tac data.txt | sed '/^----*$/ {N;a
}' | tac | sed '2,$p'
方法2
这是一个只有sed的难题(至少对我来说(。我很接近,但选择了perl。sed是图灵完备的,所以这肯定是可以翻译的。直观地说,我认为这可以用一个额外的行缓冲区来完成,我希望有人用一个仅sed的实现来回答。有时它根本站不住脚。有太多奇怪的案例,我选择了全程排队:
my @queue = ();
while (<>) {
if (/----*/) {
do {
print $queue[0];
print "n" if scalar @queue == 2;
shift @queue;
} while (scalar @queue);
print;
} else {
push @queue, $_;
}
}
do print shift @queue while scalar @queue;
我开始研究这个问题,比如:
1
0
2
1
0
这些数字表示从下面的---*
线的偏移,其中0
是----*
线。当偏移量为2
时,打印新行。
问题陈述明确表示为:print n before previous line if line ~ /----*/
。
无论如何,这是调用 输出:
$perlscript.pl data.txt
tbl
---
tmp1
col1|col2
---------
22| 33
32| 45
tbl
---
tmp2
col1|col2| col3
---------------
22| 33| 123
32| 45| 456
这可能对你有用(GNU sed(:
sed -e 'N;/---s*$/{2!i\' -e '};P;D' file
在图案空间中读取两行,如果第二行以---
结束,则在第一行上方插入一行。
注意:通常,这会在文件的开头插入一行空行,但通过检查第二行是否为文件中的第2行,可以避免这种情况。
这也可以写成:
sed 'N;/---s*$/!P;//!D;2!i\' file
最后一种解决方案的替代方案是:
sed 'N;/---[[:space:][:cntrl:]]*$/!P;//!D;2!i\' file