2

美好的一天,我想知道如何删除这样的文本块:

1    
2    
3    
4    
5    
6    
7    
8

并从第二行删除直到最后一行之前的第三行,以获得:

1    
2    
6    
7    
8

提前致谢!!!

顺便说一句,这个文本块只是一个例子,我处理的真实文本块很大,而且每个文本块的行号都不同。

4

4 回答 4

3

这可能对您有用(GNU sed):

sed '3,${:a;$!{N;s/\n/&/3;Ta;D}}' file

或者,如果您愿意:

sed '1,2b;:a;$!{N;s/\n/&/3;Ta;D}' file

这些总是打印前两行,然后构建一个三行的运行窗口。除非到达文件末尾,否则第一行会从窗口中弹出并删除。在文件末尾打印剩余的 3 行。

于 2013-10-06T07:08:54.480 回答
3

获取用于打印请求范围的行wcawk

$ awk 'NR<M || NR>N-M' M=3 N="$(wc -l file)" file
1
2
6
7
8

这使您只需更改 的值即可轻松更改范围M

于 2013-10-05T23:22:36.987 回答
2

因为你提到了巨大的,而且行号也可能不同。我会建议这个 awk 单线:

awk 'NR<3{print;next}{delete a[NR-3];a[NR]=$0}END{for(x=NR-2;x<=NR;x++)print a[x]}' file
  • 它只处理一次输入文件,而不(预先)计算总行数
  • 它在内存中存储的数据最少,在所有处理时间内,只存储了 3 行数据。
  • 如果您想更改过滤条件,例如,从 line 删除x$-y,您只需更改 oneliner 中的偏移量。

添加测试:

kent$  seq 8|awk 'NR<3{print;next}{delete a[NR-3];a[NR]=$0}END{for(x=NR-2;x<=NR;x++)print a[x]}'
1
2
6
7
8
于 2013-10-05T23:20:28.880 回答
1

使用

sed -n '
    ## Append second line, print first two lines and delete them.
    N; 
    p; 
    s/^.*$//;
    ## Read next three lines removing leading newline character inserted
    ## by the "N" command.
    N; 
    s/^\n//; 
    N; 
    :a; 
    N;
    ## I will keep three lines in buffer until last line when I will print
    ## them and exit.
    $ { p; q };
    ## Not last line yet, so remove one line of buffer based in FIFO algorithm.
    s/^[^\n]*\n//; 
    ## Goto label "a".
    ba
' infile

它产生:

1
2
6
7
8
于 2013-10-05T23:15:57.827 回答