删除与字符串的前 7 个匹配项对应的行(在模式范围内)

删除与字符串的前 7 个匹配项对应的行(在模式范围内)

我需要从 txt 文件中的模式范围 (string1-string2) 中删除与字符串前 7 次出现相对应的行。

txt文件内容示例:

whatever
xpto string1 foo2
whatever1 
string2
xpto1 another_foo
xpto string2

string2 foo1

whatever
string2 another_xpto
string2 string2
foo xpto string2 whatever 
anything else foo string2
xpto
string2
foo whatever

我需要一个带有 sed 范围的解决方案,类似这样:

sed '/string1/,/string2/d' file.txt

关键是我不知道如何延伸/string2/到与 string2 的第七个匹配相对应的行。理想的输出应该是:

whatever
anything else foo string2
xpto
string2
foo whatever

答案1

sed -e:t -e'/string1/!b' -e'/\(.*string2\)\{7\}/d;N;bt'

答案2

awk '/string1/{c=7}; c<1; {c-=gsub(/string2/, "&")}' file

cstring1最初为 0,如果找到则设置为 7 。每当 时都会打印该行c<1

该函数返回每行出现的gsub次数。string2计数器c按该值递减。

答案3

这是使用文字字符串执行您想要的操作的一种方法:

$ cat tst.awk
BEGIN { lgth = length(end) }
index($0,beg) { inBlock = 1 }
inBlock {
    rec = $0
    while ( pos = index(rec,end) ) {
        if ( ++cnt >= min ) {
            inBlock = 0
        }
        rec = substr(rec,pos+lgth)
    }
    next
}
{ print }

$ awk -v beg='string1' -v end='string2' -v min=7 -f tst.awk file
whatever
anything else foo string2
xpto
string2
foo whatever

上面将解释字符串中的反斜杠(例如\t将成为制表符),如果这是一个问题,请告诉我,因为这是一个简单的解决方法,例如使用ENVIRON[].

答案4

珀尔

perl -ne '
  if (my $e = /string1/ ... s/string2/$&/g >= 7) {
      $_ .= $e =~ /E0/ ? next : <>, redo;
  }
  print;
' file

POSIX sed:

sed -ne '
  /string1/!{p;d;}
  :loop
    n
    /string2/H
    g;s//&/7;t
  b loop
' file

输出:

whatever
anything else foo string2
xpto
string2
foo whatever

相关内容