从包含可变数据的文件中删除静态文本块
Posted
技术标签:
【中文标题】从包含可变数据的文件中删除静态文本块【英文标题】:Remove a static block of text from file containing variable data 【发布时间】:2021-10-13 09:00:56 【问题描述】:我有一个静态文本块,我需要从每晚创建的文件中删除该文本块,该文件将多个文件连接成一个文件。文本作为一个块跨越 6 行,并有一堆特殊字符,如 " 、 > 和 / 。我知道我应该能够使用 awk
、sed
或 perl
,但我不能让特殊字符的转义正确,要么出错,要么找不到块。
块总是在单独的行上:
</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 块,比如</channel> ... </link>
【参考方案1】:
假设:
所有像</channel> ... </link>
这样的块都将被删除
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
的想法是找到带有书挡</channel>
和</link>
然后d
elete 的行范围:
$ 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。以上是关于从包含可变数据的文件中删除静态文本块的主要内容,如果未能解决你的问题,请参考以下文章
如何从多个重复的 json 文件中删除一个文本块,其中文件之间有微小的变化?