首页 > 解决方案 > bash 从文件中删除文本块

问题描述

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

line 1
line 2
line 3
line 4
line 2

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

line 2
line 3

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

line 1
line 4
line 2

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

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

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

标签: bashawksed

解决方案


使用 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

推荐阅读