如何将XML item块中提取的日期插入对应块的每一行?
问题描述
我有如下XML格式的item文本块:
<item> <link>test1</link> <title>ABC1</title> <Date>Tue, 07 Jun 2023</Date> </item> <item> <link>test3</link> <title>ABC3</title> <Date>Fri, 27 Jun 2022</Date> </item> <item> <link>test2</link> <title>ABC2</title> <Date>Mon, 05 Jun 2021</Date> </item>
期望转换为如下格式:
Tue, 07 Jun 2023 <item> Tue, 07 Jun 2023 <link>test1</link> Tue, 07 Jun 2023 <title>ABC1</title> Tue, 07 Jun 2023 <Date>Tue, 07 Jun 2023</Date> Tue, 07 Jun 2023 </item> Fri, 27 Jun 2022 <item> Fri, 27 Jun 2022 <link>test3</link> Fri, 27 Jun 2022 <title>ABC3</title> Fri, 27 Jun 2022 <Date>Fri, 27 Jun 2022</Date> Fri, 27 Jun 2022 </item> Mon, 05 Jun 2021 <item> Mon, 05 Jun 2021 <link>test2</link> Mon, 05 Jun 2021 <title>ABC2</title> Mon, 05 Jun 2021 <Date>Mon, 05 Jun 2021</Date> Mon, 05 Jun 2021 </item>
我已经能用以下grep命令提取日期:
grep -oE "[A-Z][a-z][a-z],.*2[0-9][0-9][0-9]" ./file
但不知道如何将提取的日期插入到对应<item>至</item>文本块的每一行开头,需要按块处理文本,求解决思路。
解决思路与实现
核心是按<item>块分组,提取每个块内的日期后,给块内每一行前缀加上该日期。用awk可以高效完成这个需求,无需拆分文件再合并:
awk ' /<item>/ { in_item = 1 block_lines = "" next } in_item && /<Date>(.*)<\/Date>/ { date = gensub(/.*<Date>(.*)<\/Date>.*/, "\\1", "g", $0) } in_item { block_lines = block_lines $0 "\n" if (/<\/item>/) { n = split(block_lines, lines, "\n") for (i=1; i<=n; i++) { if (lines[i] != "") { print date " " lines[i] } } in_item = 0 date = "" } } ' ./file
命令解释
- 遇到
<item>时,标记进入块模式,初始化存储块内容的变量。 - 在块内匹配
<Date>行,用gensub提取纯日期文本。 - 持续累加块内所有行,直到遇到
</item>时,遍历块内每一行,拼接日期后输出。 - 退出块模式,重置变量以处理下一个item块。
如果需要直接修改原文件,部分awk版本支持-i inplace参数实现原地编辑:
awk -i inplace ' # 同上脚本内容 ' ./file
内容的提问来源于stack exchange,提问作者KarlsD
相关产品推荐
相关产品推荐

