如何解析ExtData标记的日志文件(不是完整的xml文件,但它有一些xml数据),它有一些名称 - 值对,我需要像这样掩盖它:例如:< / p>
<ExtData>Name="Jason" Value="Special"</ExtData> to <ExtData>Name="Jason" Value="XXXXXXX"</ExtData>
我需要屏蔽上面的ExtData标签值,只有在Name是Jason或某些名称时才会屏蔽,而不是每个名字。
例如:如果“DummyName”不在名称集中,那么我不想在下面更改此行。
<ExtData>Name="DummyName" Value="Garbage"</ExtData>
例如:如果“DummyName”不在名称集中,那么我不想在下面更改此行。 (请注意,值为“Jason”)
<ExtData>Name="DummyName" Value="Jason"</ExtData>
例如:如果“DummyJasonName”不在名称集中,那么我不想在下面更改此行。 (注意“Jason”介于“Dummy”和“Name”之间)
<ExtData>Name="DummyJasonName" Value="Garbage"</ExtData>
我需要在bash / shell脚本中完成所有这些。
底线是,我想通过sed / awk / match命令读取文件。 检查行中的ExtData标记。如果匹配,请阅读ExtData标记和/ ExtData标记之间的文本。在此多行文本中,提取名称。如果Name来自一组名称,则使用相同数量的'X'屏蔽其对应的“Value”数据。
请告诉我如何完成上述任务。
更新,输入行实际上可以跨越多行。
<ExtData>Name="Jason" Value="Special" </ExtData>
或者也喜欢这样:
<ExtData> Name="Jason" Value="Special" </ExtData>
谢谢!!普尼特
答案 0 :(得分:1)
在bash shell中,您可以使用此
创建文件的副本,并删除信息sed 's#\(<ExtData>Name="Jason" Value="\).*\("</ExtData>\)#\1XXXXX\2#' xml.txt > xml_xxx.txt
请注意,它不是&#34;官方&#34;更改xml文件的方法。可能会发生很多格式更改,导致此脚本无法使用,但如果您知道您的XML文件每行格式化有1个信息,那么它将起作用,就像文本文件一样,而且很快。
(问题是标记为sed和bash,如果它不涉及使用libxml2
,saxon
或其他可以解析XML节点的库进行大量xml解析
答案 1 :(得分:1)
要仅对名字Jason和Jim进行替换,请尝试:
sed -E '/Jason|Jim/{:a; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' file.xml
此命令在GNU sed上进行了测试。对于BSD / OSX sed,需要进行一些小的改动。
让我们考虑一下这个测试文件:
$ cat file.xml
<ExtData>Name="Jason" Value="Special"</ExtData>
<ExtData>Name="DummyName" Value="Garbage"</ExtData>
<ExtData>Name="Jim"
Value="OK"
</ExtData>
现在,让我们运行命令:
$ sed -E '/Jason|Jim/{:a; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' file.xml
<ExtData>Name="Jason" Value="XXXXXXX"</ExtData>
<ExtData>Name="DummyName" Value="Garbage"</ExtData>
<ExtData>Name="Jim"
Value="XX"
</ExtData>
-E
这告诉set使用扩展正则表达式。
/Jason|Jim/{...}
这告诉sed仅在包含Jason或Jim的行中运行花括号内的命令。该命令将括号分为两部分:
:a; /Value=/bb; n; ba;
第一部分读取行,直到找到包含Value=
的行。更详细地,:a
定义了标签a
。如果当前行包含/Value=/bb
,则b
分支以标记Value=
。如果它没有,我们打印出当前行并使用n
命令读入下一行。然后我们将(b
)分支回标签a
。
:b; s/(Value="X*)[^X"]/\1X/; tb;
这会将值替换为我们需要的X
个。{/ p>
更详细地说,:b
定义了标签b
。 s/(Value="X*)[^X"]/\1X/
替换X
之后我们需要的Value=
。如果进行了替换(意味着需要另一个X
),那么测试命令(t
)会告诉sed跳回标签b
,然后我们再试一次。
让我们考虑一下这个更复杂的测试文件:
$ cat file2.xml
<Misc>Name="Jason" Value="DontChange"</Misc>
<ExtData>Name="Jason" Value="Special"</ExtData>
<Misc>Name="Jason" Value="DontChange"</Misc>
<ExtData>Name="DummyName" Value="DontChange"</ExtData>
<Misc>Name="Jason" Value="DontChange"</Misc>
<ExtData>Name="Jim"
Value="OK"
</ExtData>
<Misc>Name="Jason" Value="DontChange"</Misc>
要在ExtData标记中进行更改而不在其他标记中进行更改,请尝试:
$ sed -E '/[<]ExtData[>]/{:a; /Name=/{/Name="(Jason|Jim)"/!b}; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' file2.xml
<Misc>Name="Jason" Value="DontChange"</Misc>
<ExtData>Name="Jason" Value="XXXXXXX"</ExtData>
<Misc>Name="Jason" Value="DontChange"</Misc>
<ExtData>Name="DummyName" Value="DontChange"</ExtData>
<Misc>Name="Jason" Value="DontChange"</Misc>
<ExtData>Name="Jim"
Value="XX"
</ExtData>
<Misc>Name="Jason" Value="DontChange"</Misc>
使用shell变量为名称执行上述操作:
names='Jason|Jim'
sed -E '/[<]ExtData[>]/{:a; /Name=/{/Name="'"$names"'"/!b}; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' file2.xml
这将shell变量直接替换为sed
命令。只有在您信任shell变量的来源时才应该这样做。