我有一个文件foo.txt:
$ cat foo.txt
<ul>
<li>
<p>something</p>
</li>
<li>
<p>something else</p>
</li>
</ul>
还有一个bar.txt:
$ cat bar.txt
<li>
<p>something</p>
</li>
我想要所需的输出:
<ul>
<li>
<p>something else</p>
</li>
</ul>
我试过了:
$sed '{/r bar.txt/} d' foo.txt
但它没有用,我不能这样做:
$sed '/<li>/,/</li>/ d' foo.txt
因为还有其他元素。
答案 0 :(得分:1)
这个awk单行程适用于您的示例:
awk -v RS="" '{gsub(/\n/,"\x99")}NR==FNR{t=$0;next}{gsub(t,"");gsub(/\x99/,"\n");print}' bar foo
输出不完全相同(空行),但你明白了。请参阅示例下面的简短说明。
见下面的例子:
kent$ head foo bar
==> foo <==
<ul>
<li>
<p>something</p>
</li>
<li>
<p>something else</p>
</li>
</ul>
==> bar <==
<li>
<p>something</p>
</li>
kent$ awk -v RS="" '{gsub(/\n/,"\x99")}NR==FNR{t=$0;next}{gsub(t,"");gsub(/\x99/,"\n");print}' bar foo
<ul>
<li>
<p>something else</p>
</li>
</ul>
添加简短说明
基本思路是,用不可见的char替换linebreak(在我使用\x99
的例子中),然后我们有两个单行字符串。我们可以做匹配和更换。处理完字符串后,将所有\x99
替换回linebreak以获取原始格式。这个想法也适用于sed,但有点复杂,你必须制作一个标签并玩模式/保持空间......
在我刚刚使用RS=""
的例子中(我有点懒)。您可以使用sprintf
函数来构建单行字符串,它会更通用,因为您的两个真实文件都可能有空行。 (但你的例子没有)
重点是隐形炭替换部分。
祝你好运!答案 1 :(得分:1)
sed是一个很好的工具,可以在一行上进行简单的替换,对于其他任何使用awk的东西。这是一个GNU awk解决方案:
$ gawk -v RS='\0' -v ORS= 'NR==FNR{re=$0;next} {sub(re,"")} 1' bar.txt foo.txt
<ul>
<li>
<p>something else</p>
</li>
</ul>
如果“bar.txt”可以包含RE元字符,并且您在sub()中找到导致不良匹配的那些(在匹配大量文本时不太可能),那么您需要切换到index()+ substr()的解决方案使用字符串而不是RE,例如:
$ gawk -v RS='\0' -v ORS= '
NR==FNR { str=$0; rlength=length(str); next }
rstart = index($0,str) { $0 = substr($0,1,rstart-1) substr($0,rstart+rlength) }
1' bar.txt foo.txt
<ul>
<li>
<p>something else</p>
</li>
</ul>