我一直在尝试使用sed
来完成以下操作。假设我有以下文件(注意:我的实际文件比这更复杂):
hello world
foo bar
people people
target
something
done
我想检查两个模式之间是否存在target
,在此示例中,行foo bar
和done
之间是否存在(包括两行),如果{{{},则删除整个模式1}}确实存在。
我知道如何使用此target
命令删除两个模式之间的行:
sed
但是如果字符串sed '/people.*/,/done/d' file
存在于两个字符串匹配之间,我只想删除它。
我的逻辑是这样的:
target
修改
我忘了提及在同一行的sed -n '/people.*/,/done/p' file | check if target string exists | delete entire pattern found by sed
之前和target
之后可以有任意数量的字词。
答案 0 :(得分:4)
<强>桑达强>
如果发现$start
,则会从$end
移至$pattern
:
sed ":a;N;\$!ba; s/$start.*$pattern.*$end//g"
这里有两个步骤(陈述):
<强>的Perl 强>
要处理不合适的匹配,如果允许Perl,请使用:
perl -0777 -p -e 's/$start.*?$pattern.*?$end//s'
这也将整个文件作为字符串读取。最后的/ s告诉它包含换行符作为正则表达式匹配的一部分。使用。*而不是。*?回到贪婪的搜索。
答案 1 :(得分:2)
$ awk -v RS='^$' '{sub(/\nfoo bar\n.*target.*\ndone\n/,""); print}' file
hello world
答案 2 :(得分:1)
如果文件首次包含done
,则不首先将整个文件读入内存并邀请贪婪匹配问题的方法是
sed '/^people/ { :loop; N; /\ndone/ ! b loop; /target/ d }' filename
在Mac OS X上,显然需要在结束括号之前设置换行符,因此您可以将代码放入多行字符串文字中:
sed '/^people/ { :loop; N; /\ndone/ ! b loop; /target/ d
}' filename
或者将此代码(无论如何更具可读性)放在文件中,例如foo.sed
,然后使用sed -f foo.sed filename
:
/^people/ {
:loop
N
/\ndone/ ! b loop
/target/ d
}
代码的工作原理如下:
/^people/ {
以&#34;人员&#34;
开头 :loop
N
/\ndone/ ! b loop
在循环中获取更多行,直到以done
开头(这将是第一次\ndone
出现在模式空间中)
/target/ d
如果有target
的所有内容,请丢弃整件事
}
否则照常进行(这意味着打印图案空间,因为我们没有将-n
传递给sed)。
稳健性的一个可能的改进是
sed '/^people/ { :loop; N; /\ndone$/! { $! b loop }; /target/ d }' filename
或
/^people/ {
:loop
N
/\ndone/ ! {
$ ! b loop
}
/target/ d
}
更改/\ndone$/! { $! b loop }
。这将结束文件最后一行的循环,即使没有遇到done
,这会导致文件末尾的未完成people
部分不被丢弃(除非它们包含{{ 1}})。
答案 3 :(得分:1)
迟到的回答
sed '/^foo bar *$/,/^done *$/{/^done *$/!{H;d};/^done *$/{H;g;s/.*//g;x;/.*target.*/d;s/^.//g}}'
查找/^foo bar *$/,/^done *$/
/foo bar/,/done/
此/^done *$/!{H;d}
从foo栏获取所有行,但不是最后一行“完成”并将其放入保留空间。然后从模式空间中删除这些行。
此/^done *$/{H;g;s/.*//g;x;
将最后一行“完成”并将其附加到保留空间。现在我们拥有从行foo bar到保留空间中完成的行的所有行。之后,我们清除模式空间中的所有内容,并将保留空间中的行范围与模式空间中的空行交换(这是为了在目标另一行之间保持空格时保持空白“ foo bar“和”完成“。
最后
/.*target.*/d
我们测试“目标”是否在mutli-pattern空间中。如果是,则“foo bar”和“done”之间的行范围将被删除
这样可以避免将整个文件作为单个字符串读取
示例强>
hello world
foo bar
people people
target
something
done
foo bar
.....
.....
.....
done
foo bar
people people
test
something
done
<强>结果
hello world
foo bar
.....
.....
.....
done
foo bar
people people
test
something
done
注意:正在删除从“foo bar”开始到包含“target”的行“done”的行的范围