【问题标题】:Remove duplicate XML tags with Awk?使用 awk 删除重复的 XML 标记?
【发布时间】:2021-09-07 14:30:01
【问题描述】:

我有一个很长的自定义 XML,其中有一些问题需要先解决,然后才能在 BASH 脚本中处理。

自定义 XML 如下所示:

<SOME TAGS>
<a:t>The cat</a:t>
<a:t> is</a:t>
<a:t> very</a:t>
<a:t> cute</a:t>
<SOME OTHER TAGS>
<a:t>the </a:t>
<a:t>dog </a:t>
<a:t>is </a:t>
<a:t>also </a:t>
<a:t>very </a:t>
<a:t></a:t>
<a:t>cute and nice</a:t>
<ANOTHER TAG>

这就是我想要得到的:

<SOME TAGS>
<a:t>The cat is very cute</a:t>
<SOME OTHER TAGS>
<a:t>the dog is also very cute and nice</a:t>
<ANOTHER TAG>
  • 句子应以 开头并以 结尾
  • 句子由一些其他标签分隔(我没有所有可能标签的列表)。
  • 我不知道每个句子有多少个单词。

我尝试在第一个 上使用带有 grep 的循环,然后使用 sed 删除其他标签,但它显然不起作用。

是否可以这样做(可能使用 Awk)?

提前谢谢你,

【问题讨论】:

  • 听起来像是 XSLT 的工作。
  • 谢谢!我会仔细看看的。如果可能的话,我仍然更喜欢使用 Shell 脚本来执行此操作(因为这是长 Bash 脚本的一部分)。

标签: awk sed


【解决方案1】:

对于perl,假设&lt;a:t&gt;...&lt;/a:t&gt; 始终在自己的行中,并且没有其他文本。由于整个输入都被 slurped,因此对于非常大的文件,这不是一个好的解决方案。

$ perl -0777 -pe 's%(^<a:t>.*</a:t>\n)+%$&=~s#(?<!\A)<a:t>|</a:t>\n(?!\z)##rg%gme' ip.txt 
<SOME TAGS>
<a:t>The cat is very cute</a:t>
<SOME OTHER TAGS>
<a:t>the dog is also very cute and nice</a:t>
<ANOTHER TAG>
  • -0777 啜饮整个输入
  • (^&lt;a:t&gt;.*&lt;/a:t&gt;\n)+ 匹配以&lt;a:t&gt; 开头并以&lt;/a:t&gt; 结尾的一行或多行(. 不会匹配没有s 标志的换行符)
    • (?&lt;!\A)&lt;a:t&gt;|&lt;/a:t&gt;\n(?!\z) 将匹配 &lt;a:t&gt;&lt;/a:t&gt;,但匹配字符串的开头/结尾除外
  • e 标志允许在替换部分使用 Perl 代码,在这里用于执行另一个替换
  • m 标志允许 ^ 在每一行的开头匹配

【讨论】:

  • 谢谢!我也会测试这个解决方案。我在一些非常大的文件上运行它。我不确定哪种解决方案(Perl 或 Awk)会更快。
  • Awk 解决方案可能更健壮,因为它实际上一次只读取一个文件,而这个 Perl 解决方案将整个文件读入内存。如果您的文件大于可用 RAM,它会起作用,但速度会很慢。
【解决方案2】:

如果你的 XML 字面意思是这种常规的,那应该很容易。在 XML 上使用正则表达式和面向行的工具的问题在于,XML 语法允许在换行符和空格方面有很多变化。但如果您的输入没有,那么应该可以使用以下内容。

awk '/^<a:t>/ {
    sub(/^<a:t> */, ""); sub(/ *<\/a:t>/, "");
    sent = (sent ? sent " " : "<a:t>") $0
    next }
sent { print sent "</a:t>"; sent="" }
1
END { if(sent) print sent "</a:t>" }' file.xml

我们将当前句子收集到字符串变量sent中,然后当我们看到与句子标签不同的标签或到达输入文件末尾时将其打印出来。

在 END 块中重复打印是没有吸引力的,但是我懒得回去重构了。

演示:https://ideone.com/B8SHOG

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多