首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >解析行和更改文本的位置

解析行和更改文本的位置
EN

Stack Overflow用户
提问于 2016-08-03 19:14:34
回答 2查看 254关注 0票数 1

如何解析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=“特别”

谢谢!!普奈

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-04 22:35:29

要只替换Jason和Jim的名字,请尝试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sed -E '/Jason|Jim/{:a; /Value=/bb; n; ba; :b; s/(Value="X*)[^X"]/\1X/; tb; }' file.xml

该命令在GNU上进行了测试。对于BSD/OSX sed,需要做一些小的改动。

示例

让我们考虑一下这个测试文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ cat file.xml
<ExtData>Name="Jason" Value="Special"</ExtData>
<ExtData>Name="DummyName" Value="Garbage"</ExtData>
<ExtData>Name="Jim"
    Value="OK"
        </ExtData>

现在,让我们运行我们的命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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的行运行大括号内的命令。大括号内部的命令分为两部分:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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定义了一个标签bs/(Value="X*)[^X"]/\1X/取代了我们在Value=之后需要的下一个X。如果进行了替换(意味着需要另一个X ),那么test命令(t)告诉sed跳回标签b,然后再试一次。

将更改限制在ExtData标记中

让我们考虑一下这个更复杂的测试文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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标记进行更改,但不对其他标记进行更改,请尝试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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变量执行上述操作,请执行以下操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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变量的源时,才应该这样做。

票数 1
EN

Stack Overflow用户

发布于 2016-08-04 12:58:59

在bash中,您可以创建一个文件的副本,其中删除的信息可以使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sed 's#\(<ExtData>Name="Jason" Value="\).*\("</ExtData>\)#\1XXXXX\2#' xml.txt > xml_xxx.txt

请注意,这不是更改xml文件的“正式”方式。可能会发生许多格式更改,从而使这个脚本毫无用处,但是如果您知道XML文件的每一行有一个信息是这样格式化的,那么它就会正常工作,就像一个文本文件一样,而且速度很快。

(此外,问题是标记了sed和bash,如果不是这样的话,将涉及使用libxml2saxon或其他可以解析xml节点的库进行大量的XML解析)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38757920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文