我有一个包含很多这样的行的日志文件:
2021/09/03-13:11:05;QUEUE.INBOUND;4;ID:myhost.mydomain.net-7756-1629822315072-199:973:1:1:1;MISC;"<?xml version="1.0" encoding="UTF-8"?> <RootElement xmlns="urn:namespace:entity/1" tstamp="2021-02-29T12:11:00Z" object="urn:domain:entity:ID1234"><Active lang="en" value="true">active</Active><Name lang="en">Some Name</Name><ShortName lang="en">shortname</ShortName><Phone number="+416458838829" lang="en">+416458838829</Phone><Email>[email protected]</Email><Longitude>7.043786</Longitude><Latitude>47.239036</Latitude></RootElement>"
(XML 比这个大,但这只是一个示例。)
我的目标是将每一行中的每个 XML 提取到一个专用文件中。如果日志包含 10 行,则将创建 10 个文件。
我是这样开始的:
more mylogfile.txt | sed -r 's!^.*\s(<RootElement.*\sobject="urn:domain:entity:([A-z0-9]*)"><Active.*</RootElement>).*!echo "\1" | xmlstarlet fo > "\2.xml"!e; d'
这个想法是提取对象 urn 中的 ID 并将其用作文件名(id 在文件中是唯一的)。
问题:
单独执行“echo”命令时
more mylogfile.txt | sed -r 's!^.*\s(<RootElement.*\sobject="urn:domain:entity:([A-z0-9]*)"><Active.*</RootElement>).*!echo "\1"!e; d'
我注意到 XML 中的双引号刚刚被擦除,并且xmlstarlet
命令(在第一次尝试中)只会出错。
Active 元素的示例将变为:
<Active lang=en value=true>active</Active>
sed
我知道在和中执行 bash 命令时语法有一些技巧echo
,但我尝试了几种不同的语法(例如删除 \1 周围的“”、使用printf
、改为使用xargs
externalsed
等),但没有一个成功。
我使用的是 Ubuntu 发行版 18.04(Windows 下的 WSL 1)。
echo
或“ ”命令中是否有任何选项sed
s!...!...!e
可以改善此问题?
(如果你找到更有效的方法,我也很开放)
答案1
您需要先使用 转义引号s/"/\\"/g
。这样可以防止它们被吃掉echo
。
然后记得调整您的搜索模式。您需要匹配\"
而不是"
,并且反斜杠需要转义,因此它需要位于\\"
搜索模式中:
sed -E 's/"/\\"/g;s!^.*\s(<RootElement.*\sobject=\\"urn:domain:entity:([A-Za-z0-9]*)\\"><Active.*</RootElement>).*!echo "\1"!e;d'