我需要从 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
c
string1
最初为 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