bash从文件中删除文本块

时间:2018-09-03 15:31:13

标签: bash awk sed

假设我有一个包含文本行的输入文件:

line 1
line 2
line 3
line 4
line 2

现在假设我想检查我的输入文件是否包含

line 2
line 3

并删除该文本块(如果找到)。这将给出:

line 1
line 4
line 2

请注意,我不想删除每次出现的line 2line 3;但前提是要一个接一个地找到它们。 (实际上,我要检查一个5行的块,而不仅仅是两个占位符之间的任何代码块,而是让示例保持简单)。

我调查了awk,但很快就变得复杂了(我还没有准备好;因为我觉得这不是正确的方法,会用5行爆炸……)

awk '/line 2/ {if (line0) {print line0; line0=""}; line0=$0}' input.txt

4 个答案:

答案 0 :(得分:3)

使用GNU awk进行多字符RS和RT的一种方法:

$ awk -v RS='(^|\n)line 2\nline 3\n' '{ORS=(RT ~ /^\n/ ? "\n" : "")} 1' file
line 1
line 4
line 2

任何awk:

$ cat file
line 2
line 3
line 1
line 2
line 3
line 4
line 2
line 3

$ awk '
    { rec = rec $0 RS }
    END {
        rec = RS rec
        gsub(/\nline 2\nline 3\n/,RS,rec)
        gsub(/^\n|\n$/,"",rec)
        print rec
    }
' file
line 1
line 4

以上假设您要使用正则表达式进行匹配,因为这就是您发布的代码所做的。如果您想进行文字字符串匹配,也可以通过一些按摩来做到这一点:

$ cat tst.awk
{ rec = rec $0 RS }
END {
    while ( beg = index(RS rec,RS block RS) ) {
        out = out substr(RS rec,1,beg-1)
        rec = substr(RS rec,beg+length(block)+2)
    }
    print substr(out rec,2)
}

$ awk -v block='line 2\nline 3' -f tst.awk file
line 1
line 4

答案 1 :(得分:1)

使用gnu sed

   A        B         C          D  
Actual   Appoint.   Month      Count  
03Feb18  03Feb18    February     2  
10Feb18  15Feb18  
18Feb18  15Feb18

答案 2 :(得分:1)

不是RxJS,但是@triplee指出,这在Perl 5中是很简单的。在五行输入文件中,您在上方显示为awk

foo.txt

产生所需的三行输出。

说明:

  • perl -0777 -pe 's{^line 2\nline 3\n}{}gm' foo.txt 使perl以一个字符串的形式读取整个输入(请参见perlrun)。
  • 正则表达式上的-0777修饰符使/m在行首匹配(请参见perlre)。
  • 编辑 ^也将在文件开头匹配,因此即使行之前没有换行符,您也可以检测到它们。
  • 行之间的分隔符为文字^,因为\n$之前的{em>匹配,且\n/m修饰符匹配。因此,仅匹配\n会更容易。

感谢this U&L SE answerStéphane Chazelas的基础知识。

答案 3 :(得分:0)

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

sed '/^line 2$/!b;N;/^line 3$/Md;P;D' file

如果一行与字符串line 2不匹配,请打印该行并开始下一个循环。否则,请添加以下行,如果该行与字符串line 3相匹配,请删除这两行。否则,打印然后删除第一行并重复。