【问题标题】:How to remove from file specific content from another file?如何从另一个文件中删除文件的特​​定内容?
【发布时间】:2013-04-05 11:33:02
【问题描述】:

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

因为还有其他元素。

【问题讨论】:

  • 在 sed 中,r 命令将文件读入输出流,而不是作为脚本的一部分。您使用 sed -f script ... 加载脚本,但这不起作用,因为 bar.txt 不是有效的 sed 脚本。您需要一个中间步骤来将 bar.txt 转换为有效的 sed 命令。

标签: shell sed command


【解决方案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>

添加简短说明

基本思想是,用不可见的字符替换换行符(在示例中我使用\x99),然后我们有两个单行字符串。我们可以进行匹配和替换。在我们处理完字符串后,将所有\x99 替换回换行符以获得原始格式。这个想法也适用于 sed,但有点复杂,你必须制作一个标签并使用模式/保持空间......

在示例中我只是使用了RS=""(我有点懒)。您可以使用sprintf 函数来构建单行字符串,它会更通用,因为您的两个真实文件都可能有空行。 (但是你的例子没有)

重点是不可见的字符替换部分。

祝你好运!

【讨论】:

  • 不幸的是它没有用。标签之间有许多换行符和空格(常规 HTML),尽管我已将 \n 替换为 \n+ - 它没有帮助...
  • \n+ 是错误的。空格和多\n 没问题。如果你有空行,那可能是个问题。我在回答中提到过。您可以使用 awk 中的 sprintf 函数来解决空行问题。我当前的代码在这里适用于您的示例。
【解决方案2】:

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()s 解决方案使用字符串而不是 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>

【讨论】:

  • 它们都不起作用:(也许“bar.txt”太复杂了?:&lt;li&gt; &lt;div style="slidecontent"&gt; &lt;div class="slideleft"&gt; &lt;a href="http://url/"&gt;&lt;img src="img/img.jpg" border="0"/&gt;&lt;/a&gt; &lt;/div&gt; &lt;div class="slide"&gt; &lt;div class="tx"&gt; &lt;h2&gt;headline&lt;/h2&gt; &lt;p&gt;&lt;strong&gt;something&lt;br/&gt; something&lt;/strong&gt;&lt;br/&gt;&lt;br/&gt; something&lt;br&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/li&gt; (它分布在多行)
  • “它们都不起作用”不会帮助我们解决问题,因为它没有告诉我们问题是什么。在评论中发布一堆 HTML 也无济于事。如果您的输入文件看起来像您在问题中发布的示例输入,我发布的脚本肯定会起作用。如果您的真实输入看起来不像您的示例输入,那么该脚本当然将不起作用。尝试在您的输入文件上运行 cat -v 以查看行尾是否有 control-M,如果您在 Windows 上创建输入文件就会发生这种情况。
  • @user2275835 - “to_remove”的内容与“index.html”的内容不匹配?后者在以“

    ”开头的行和“

    ”之间有自己的“
    ”行,并且

    行末尾的文本在两者之间完全不同. 我将发布 2 并突出显示差异。

  • 哦,我的天哪....因为错误的文本选择浪费了很多时间...非常感谢 Ed!
  • @user2275835 如果您有满意的答案,请不要忘记点击答案旁边的复选标记,这样其他发帖人就不会浪费时间想出不同的答案。
  • 猜你喜欢
    • 2013-01-12
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 2015-03-30
    • 1970-01-01
    • 2011-06-14
    相关资源
    最近更新 更多