我正在尝试回答一个问题。它涉及使用命令recode
。该命令必须解析特定行,而其余部分保持不变。文件就是xml
文件。例子:
<ITEM_ID>foo</ITEM_ID>
<PRODUCTNAME>bar</PRODUCTNAME>
<DESCRIPTION><p>foo</p><p> </p><p> </p></DESCRIPTION>
<URL>bar</URL>
<IMGURL>foo</IMGURL>
<IMGURL_ALTERNATIVE></IMGURL_ALTERNATIVE>
所需的输出应该是:
<ITEM_ID>foo</ITEM_ID>
<PRODUCTNAME>bar</PRODUCTNAME>
<DESCRIPTION><p>foo</p><p> </p><p> </p></DESCRIPTION>
<URL>bar</URL>
<IMGURL>foo</IMGURL>
<IMGURL_ALTERNATIVE></IMGURL_ALTERNATIVE>
注意:该命令recode
按预期工作。避免标签的转换DESCRIPTION
可以稍后解决,这不是问题的一部分。
应更改的行是以 开头的行<DESCRIPTION>
。
我真的不擅长awk
静止,预期的命令是这样的:
awk '/<DESCRIPTION>/ { $0 = print $0 "| recode ..html" }1' foo.txt
这当然行不通。
我应该如何实现这个目标?
答案1
您需要使用 awkgetline
将输出读入变量。您还需要正确设置区域设置,以便重新编码能够按预期工作。尝试这个:
$ LC_ALL=C gawk '/DESCRIPTION/{
"echo \""$0"\" | recode ..html" | getline ff; print ff
}' file
<DESCRIPTION><p>foo</p><p> </p><p> </p></DESCRIPTION>
答案2
假设文档格式良好,有一些根节点root
......
$ cat file.xml
<root>
<ITEM_ID>foo</ITEM_ID>
<PRODUCTNAME>bar</PRODUCTNAME>
<DESCRIPTION><p>foo</p><p> </p><p> </p></DESCRIPTION>
<URL>bar</URL>
<IMGURL>foo</IMGURL>
<IMGURL_ALTERNATIVE></IMGURL_ALTERNATIVE>
</root>
然后,
$ xmlstarlet ed -u '/root/DESCRIPTION' -v "$( xmlstarlet sel -t -c '/root/DESCRIPTION/*' file.xml )" file.xml
<?xml version="1.0"?>
<root>
<ITEM_ID>foo</ITEM_ID>
<PRODUCTNAME>bar</PRODUCTNAME>
<DESCRIPTION><p>foo</p><p> </p><p> </p></DESCRIPTION>
<URL>bar</URL>
<IMGURL>foo</IMGURL>
<IMGURL_ALTERNATIVE/>
</root>
这里发生的事情是xmlstarlet sel
用来提取节点下的节点的副本/root/DESCRIPTION
。这就是它的xmlstarlet sel -t -c '/root/DESCRIPTION/*' file.xml
作用,它返回字符串<p>foo</p><p> </p><p> </p>
。
/root/DESCRIPTION
然后通过命令将该字符串用作节点的新文本值xmlstarlet ed
。新值来自命令替换。
请注意,该值会自动进行 XML 编码。