我一直在尝试使用 sed
来完成以下任务。假设我有以下文件(注意:我的实际文件比这个更复杂):
hello world
foo bar
people people
target
something
done
我想检查 target
是否存在于两个模式之间,在这个例子中,在行 foo bar
和 done
之间(包括两行) , 如果 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
之前和 target
之后可以有任意数量的单词。
最佳答案
安全
如果在其中找到 $pattern
,这将从 $start
删除到 $end
:
sed ":a;N;\$!ba; s/$start.*$pattern.*$end//g"
这里有两个步骤(语句):
- 将整个文件作为单个字符串读取(根据文件大小可能会很糟糕)。有关很好的解释,请参阅 https://stackoverflow.com/a/1252191 .唯一的区别是 $!ba 之前的附加反引号,以使其与双引号一起使用,这对于在 sed 行内传递 Bash 变量很有用。
- 常规的旧搜索/替换。
Perl
要处理非贪婪匹配,如果允许使用 Perl,请使用:
perl -0777 -p -e 's/$start.*?$pattern.*?$end//s'
这也会将整个文件作为字符串读取。末尾的/s 告诉它在正则表达式匹配中包含换行符。使用 .* 而不是 .*?回到贪婪搜索。
关于regex - bash-delete 如果字符串存在于两个模式之间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27747314/