如何解析ExtData标记的日志文件(不是完整的xml文件,但它有部分xml数据),它有一些名称-值对,我需要像这样屏蔽它:例如:
Name="Jason“Value=”专用“转Name="Jason”Value="XXXXXXX“
我需要像上面那样掩蔽ExtData标记值,只有当名称是Jason或某一组名称时,而不是针对每个名称。
如果"DummyName“不是在一组名字中,那么我不想在下面的一行中修改。
Name="DummyName“Value=”垃圾“
如果"DummyName“不是在一组名字中,那么我不想在下面的一行中修改。(请注意,值为"Jason")
Name="DummyName“Value="Jason”
如果"DummyJasonName“不是在一组名字中,那么我不想在下面的一行中修改。(请注意“假人”和“名称”之间的"Jason“)
Name="DummyJasonName“Value=”垃圾“
我需要用bash/shell脚本来完成所有这些工作。
底线是,我想通过sed/awk/match命令读取一个文件。检查行中的ExtData标记。如果匹配,读取ExtData标记和/ExtData标记之间的文本。在这个多行文本中,提取名称。如果名称来自一组名称,则用相同数量的“X”掩蔽其对应的“值”数据。
请让我知道如何完成上述任务。
更新时,输入行实际上可以跨越多行。
Name=“杰森”Value=“特别”
或者像这样:
Name=“杰森”Value=“特别”
谢谢!!普奈
发布于 2016-08-04 22:35:29
要只替换Jason和Jim的名字,请尝试:
sed -E '/Jason|Jim/{:a; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' file.xml
该命令在GNU上进行了测试。对于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的行运行大括号内的命令。大括号内部的命令分为两部分:1. `:a; /Value=/bb; n; ba;`
第一部分读取行,直到找到包含Value=
的行为止。更详细地说,:a
定义了一个标签a
。如果当前行包含/Value=/bb
,则将分支标记为b
。如果没有,我们将输出当前行并使用n
命令读取下一行。然后我们将分支(b
)返回到标签a
。
2. :b; s/(Value="X*)[^X"]/\1X/; tb;
这将用我们需要的任意数量的X
替换这个值。
更详细地说,:b
定义了一个标签b
。s/(Value="X*)[^X"]/\1X/
取代了我们在Value=
之后需要的下一个X
。如果进行了替换(意味着需要另一个X
),那么test命令(t
)告诉sed跳回标签b
,然后再试一次。
将更改限制在ExtData标记中
让我们考虑一下这个更复杂的测试文件:
$ 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变量的源时,才应该这样做。
发布于 2016-08-04 12:58:59
在bash中,您可以创建一个文件的副本,其中删除的信息可以使用
sed 's#\(<ExtData>Name="Jason" Value="\).*\("</ExtData>\)#\1XXXXX\2#' xml.txt > xml_xxx.txt
请注意,这不是更改xml文件的“正式”方式。可能会发生许多格式更改,从而使这个脚本毫无用处,但是如果您知道XML文件的每一行有一个信息是这样格式化的,那么它就会正常工作,就像一个文本文件一样,而且速度很快。
(此外,问题是标记了sed和bash,如果不是这样的话,将涉及使用libxml2
、saxon
或其他可以解析xml节点的库进行大量的XML解析)
https://stackoverflow.com/questions/38757920
复制相似问题