如何从其他文件中删除文件特定内容?

时间:2013-04-12 19:55:54

标签: shell sed command

我有一个文件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

因为还有其他元素。

2 个答案:

答案 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>