从包含可变数据的文件中删除静态文本块

Posted

技术标签:

【中文标题】从包含可变数据的文件中删除静态文本块【英文标题】:Remove a static block of text from file containing variable data 【发布时间】:2021-10-13 09:00:56 【问题描述】:

我有一个静态文本块,我需要从每晚创建的文件中删除该文本块,该文件将多个文件连接成一个文件。文本作为一个块跨越 6 行,并有一堆特殊字符,如 " 、 > 和 / 。我知道我应该能够使用 awksedperl,但我不能让特殊字符的转义正确,要么出错,要么找不到块。

块总是在单独的行上:

</channel>
</rss><?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[Example]]></title>
<description><![CDATA[Example]]></description>
<link><![CDATA[https://www.example.com/]]></link>

我想改变

</item>
</channel>
</rss><?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[Example]]></title>
<description><![CDATA[Example]]></description>
<link><![CDATA[https://www.example.com/]]></link>
<item>

进入

</item>
<item>

它在通过连接多个流创建的文件中出现 8 次。

【问题讨论】:

向我们展示预期的结果 Don't Parse XML/html With Regex. 我建议使用 XML/HTML 解析器 (xmlstarlet, xmllint ...)。 请在您的问题中添加示例输入(有效的 XML、无描述、无图像、无链接)以及该示例输入所需的输出(无评论)。 我更新了问题 这个块有什么特别/特别之处,还是你想删除 ALL 块,比如&lt;/channel&gt; ... &lt;/link&gt; 【参考方案1】:

假设:

所有像&lt;/channel&gt; ... &lt;/link&gt;这样的块都将被删除 OP 已声明该文件有 8x 个这些块 实际数据的格式与 OP 的示例输入中的一样(否则,正如 Cyrus 所提到的,XML/HTML 解析器可能更合适)

样本数据:

$ cat sample.dat
</item> keep this line
</channel>
</rss><?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[Example]]></title>
<description><![CDATA[Example]]></description>
<link><![CDATA[https://www.example.com/]]></link>
<another_item> keep this line

<link><![CDATA[https://www.example.com/KEEP_THIS_LINE]]></link>

</another_item> keep this line
</channel>
</rss><?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[Example]]></title>
<description><![CDATA[Example]]></description>
<link><![CDATA[https://www.example.com/]]></link>
</one_more_item> keep this line

一个sed 的想法是找到带有书挡&lt;/channel&gt;&lt;/link&gt; 然后delete 的行范围:

$ sed '/<\/channel>/,/<\/link>/d' sample.dat
</item> keep this line
<another_item> keep this line

<link><![CDATA[https://www.example.com/KEEP_THIS_LINE]]></link>

</another_item> keep this line
</one_more_item> keep this line

一旦 OP 验证了答案的准确性,如果打算用结果覆盖输入文件,则可以添加 -i 标志。

【讨论】:

几乎,是删除文件末尾的块的一部分,对我来说没什么大不了的,因为我可以重新添加它,但这对于查看此内容的人来说是个问题一个通用的解决方案。 我不确定如何删除part of the block ...您能否用您正在谈论的示例更新问题:part of the block at the end of the file 文件以 结尾,这会被您的 sed 命令删除,即使其余文本不存在,我只是将这些标签读到文件末尾这对我有用。感谢您的帮助【参考方案2】:

使用 GNU awk 进行多字符 RS:

$ awk -v RS='^$' -v ORS= 'NR==FNRrmv=$0; next s=index($0,rmv)$0=substr($0,1,s-1) substr($0,s+length(rmv)) 1' remove file
</item>
<item>

以上内容适用于文件中的任何字符,因为它只是进行文字字符串比较并且在这些输入文件上运行:

$ head remove file
==> remove <==
</channel>
</rss><?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[Example]]></title>
<description><![CDATA[Example]]></description>
<link><![CDATA[https://www.example.com/]]></link>

==> file <==
</item>
</channel>
</rss><?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<title><![CDATA[Example]]></title>
<description><![CDATA[Example]]></description>
<link><![CDATA[https://www.example.com/]]></link>
<item>

【讨论】:

似乎只删除了第一个实例 @markp-fuso 对,这就是示例输入中的全部内容。如果 OP 希望删除 1 个以上的实例,则应在示例输入/输出中至少包含 2 个。 实例之间的文本大约是 50,000 个字符 @eliblaustein 如果您说您不能在示例中显示 2 个实例,因为在您的真实数据中它们之间有 50,000 个字符 - 不,我们不需要看到所有这些,只需在每个块之间创建一个minimal reproducible example,并在您的问题中显示 that

以上是关于从包含可变数据的文件中删除静态文本块的主要内容,如果未能解决你的问题,请参考以下文章

无法从数据流中的 GCS 读取我的配置文本文件(列名)

如何从多个重复的 json 文件中删除一个文本块,其中文件之间有微小的变化?

java网站页面静态化方案

为 Zend Framework 首页存储静态文本

在 wxPython 中,如何使用 sizers 在滑块下方左右对齐静态文本?

(我是初学者)第一次用静态块