使用单个sed调用来引导前H行并尾随最后的T行

问题描述 投票:2回答:3

我写了一个C程序一段时间,通过同时执行headtail来总结一个文本文件,只有一个管道输入读取。例:

$ headtail -h 3 -t 3 < /tmp/x10
line01
line02
line03
... 4 output lines omitted ...
line08
line09
line10

它有效,但我觉得很脏,没有一个漂亮的sed别名可以做到这一点。找到这个使用sedprint the last N lines的答案,现在似乎可以实现,但我不是那里。

例如,个人headtail工作:

$ sed -n -e '1,3p' < /tmp/x10
line01
line02
line03

$ sed -n -e ':a; $p; N; 4,$D; ba' < /tmp/x10
line08
line09
line10

但我尝试合并两者失败了:

$ sed -n -e '1,3p; :a; $p; N; 4,$D; ba' < /tmp/x10
line01
line08
line09
line10

如果文件中的H + T> N行(如cat),它也可以很好地工作,并且还可以打印一个分隔符,指示从中间省略了一些行(省略的数字会很好,但我没有它可以活着)。

awk sed text-processing
3个回答
1
投票

不需要C程序或复杂的sed脚本,您只需要一个清晰,简单,便携,高效的awk脚本:

$ seq 10 | awk -v h=3 -v t=3 'NR<=h; {a[NR%t]=$0} END{for (i=1; i<=t; i++) print a[(NR+i)%t]}'
1
2
3
8
9
10

$ seq 10 | awk -v h=3 -v t=3 'NR<=h; {a[NR%t]=$0} END{print "skipped", NR-(t+h); for (i=1; i<=t; i++) print a[(NR+i)%t]}'
1
2
3
skipped 4
8
9
10

如果范围重叠,你没有说你的要求是什么,所以我只是在两个输出部分中包含重叠的行并为跳过打印负值,例如:

$ seq 10 | awk -v h=7 -v t=5 'NR<=h; {a[NR%t]=$0} END{print "skipped", NR-(t+h); for (i=1; i<=t; i++) print a[(NR+i)%t]}'
1
2
3
4
5
6
7
skipped -2
6
7
8
9
10

但无论你对边缘情况的要求是什么,它们都是微不足道的。


1
投票

尝试:

$ seq 10 | sed -n -e '1,3{p;b}; :a; $p; N; 7,$D; ba'
1
2
3
8
9
10

7来自加上3(头)加上3(尾巴)加上1。)

如果我们将尾部从3增加到7,我们得到整个文件:

$ seq 10 | sed -n -e '1,3{p;b}; :a; $p; N; 12,$D; ba'
1
2
3
4
5
6
7
8
9
10

123(头)加上7(尾巴)加1.)

How it works

  • 1,3{p;b} 对于前三行中的任何一行,我们打印它们(p)然后分支(b)超过代码中的其余命令。
  • :a; $p; N; 7,$D; ba 这与以前的工作方式相同,只是这些行永远不会看到前三行。因此,我们必须将D命令的起点更改为7

1
投票

这可能适合你(GNU sed):

sed -E '1,5p;H;$!d;x;s/.*((\n[^\n]*){3})$/\1/;s/./==========&/' file

这将打印由==========分隔的前五行和后三行。

这些命令使用前n行的范围,所有行都存储在保留空间中。在文件的末尾,保留空间减少到所需的行数,并且前导换行符被分隔符替换。

另一种解决方案,内存密集程度较低但限制在标题线等于或小于拖尾线的情况是:

sed ':a;$!{N;;s/[^\n]\+/&/5;3{p;x;s/^/==========/p;x};Ta};$P;D' file

这里前三行和后五行用分隔符打印。

© www.soinside.com 2019 - 2024. All rights reserved.