解析线并更改一些文本到位

时间:2016-08-04 03:14:35

标签: xml bash parsing sed

如何解析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>

谢谢!!普尼特

2 个答案:

答案 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,如果它不涉及使用libxml2saxon或其他可以解析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的行中运行花括号内的命令。该命令将括号分为两部分:

    1. :a; /Value=/bb; n; ba;

      第一部分读取行,直到找到包含Value=的行。更详细地,:a定义了标签a。如果当前行包含/Value=/bb,则b分支以标记Value=。如果它没有,我们打印出当前行并使用n命令读入下一行。然后我们将(b)分支回标签a

    2. :b; s/(Value="X*)[^X"]/\1X/; tb;

      这会将值替换为我们需要的X个。{/ p>

      更详细地说,:b定义了标签bs/(Value="X*)[^X"]/\1X/替换X之后我们需要的Value=。如果进行了替换(意味着需要另一个X),那么测试命令(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变量的来源时才应该这样做。