我有一个 XML 格式的文件,
{XML file with similar tags - SubRecord and Property}
...
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">Value i'm Concerned to Modify</Property>
</SubRecord>
...
我的要求。是获取此特定子记录的“默认”值并根据条件更新它。为此,我需要访问这个特定的标签“名称”并修改其值。
有没有办法使用SED/AWK/GREP?
编辑:根据@terdon的更新:
- 所有部分都只有一行吗?不
- 默认值总是最后一个吗?始终从顶部第三个(名称、提示、默认)
- 有什么区分大小写的吗?就是一切?区分大小写。
- 有空行吗?希望不会。但我可以做一些预先准备来删除它们。
- 文件是否缩进?是的。
例子: ...
<SubRecord>
<Property Name="Name">Search</Property>
<Property Name="Prompt">Some Text</Property>
<Property Name="Default">abc.txt</Property>
</SubRecord>
...
在具有类似Propert和SubRecords的大型XML文件中,我需要首先找到“Search”参数的所有属性。
找到“搜索”后,我需要检查其默认值。如果是 abc.txt,那么我需要保留该值,如果是 xyx,我仍然需要保留。除了 abc.txt 或 xyz 之外,我需要用 abc.txt 更新它。
答案1
XML 应该由支持 XML 的工具来处理。
XMLStarlet 就是这样一个工具。
这是设置属性为且值不是或 的Property
节点的值的方法:Name
Default
abc.txt
xyx
xml ed -u '//SubRecord/Property[@Name="Default" and . != "xyx" and . != "abc.txt"]' -v 'abc.txt' file.xml
给定一个如下所示的 XML 文件:
<?xml version="1.0"?>
<Record>
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">zzz</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">abc.txt</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">xyx</Property>
</SubRecord>
</Record>
这会产生
<?xml version="1.0"?>
<Record>
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">abc.txt</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">abc.txt</Property>
</SubRecord>
<SubRecord>
<Property Name="Name">My Main Search Keyword</Property>
<Property Name="Prompt">Dummy</Property>
<Property Name="Default">xyx</Property>
</SubRecord>
</Record>
(第一条SubRecord
已修改)
XMLStarlet 可从http://xmlstar.sourceforge.net/(但首先检查你自己的包管理器)。有时它的可执行文件被调用xmlstarlet
而不仅仅是xml
.
答案2
您无法使用正则表达式解析 [X]HTML/XML。因为 HTML/XML 无法被正则表达式解析。 Regex 不是一个可以用来正确解析 HTML/XML 的工具。正则表达式是一种不够复杂的工具,不足以理解 HTML/XML 使用的结构。 HTML/XML 不是正则语言,因此无法通过正则表达式进行解析。正则表达式查询无法将 HTML/XML 分解为其有意义的部分。即使 Perl 使用的增强型不规则正则表达式也无法胜任解析 HTML/XML 的任务。你永远不会让我崩溃。 HTML/XML 是非常复杂的语言,无法通过正则表达式进行解析。即使 Jon Skeet 也无法使用正则表达式解析 HTML/XML。每次您尝试使用正则表达式解析 HTML/XML 时,邪恶的孩子就会流下处女的鲜血,而俄罗斯黑客就会侵占您的 Web 应用程序。用正则表达式解析它们会将被污染的灵魂召唤到生者的领域。它们和正则表达式就像爱情、婚姻和杀婴仪式一样紧密相连。 <center>无法容纳,为时已晚。正则表达式和 HTML/XML 在同一个概念空间中的力量会像水腻子一样摧毁你的思想。如果你用正则表达式进行解析,你就屈服于他们和他们亵渎的方式,这注定我们所有人都要为那个名字无法在基本多语言平面中表达的人进行非人的辛劳,他来了。 HTML-plus-regexp 将在你观察时液化感知者的神经,你的心灵在恐怖的袭击中枯萎。基于 Rege̿̔̉x 的 HTML/XML 解析器是杀死 StackOverflow 的毒瘤太晚了,太晚了,我们无法得救了孩子的转移确保正则表达式会消耗所有活体组织(除了 HTML,正如之前所预言的,它不能)亲爱的主啊,请帮助我们,如何才能在这场灾难中幸存下来使用正则表达式解析 HTML 注定了人类将永远遭受可怕的折磨和安全漏洞使用雷吉x作为处理HTML的工具建立了一个brea这个世界之间的ch以及 c͒ͪo͛ͫ 中断实体的可怕领域(如 SGML 实体,但是更腐败)只是一瞥reg 世界的SEHTML 的 ex 解析器将 ins坦特利运输应用程序程序员意识i恩托奥尔不断的尖叫,他来了,致命的、狡猾的正则表达式感染将到来我吞噬你的HTML 解析器、应用程序和一直存在,就像 Visual Basic 一样,只会更糟他来了他来了英语不准右边e com̡e̶s, ̕h̵is un̨ho͞ly radiańcé de分析所有 enli̍̈́̂̈́限制、HTML 标签lea͠ki̧n͘g fr̶ǫm ̡yo͟你的眼睛͢s̸ ̛l̕ik͏e liquid pain,正则表达式解析之歌将exti痛苦的声音来自sp的塔尔曼在这里我可以看到它你能看到̲͚̖͔̙î̩́t̲͎̩̱͔́̋̀它很漂亮何芬inal snuf
澳谎言男人的一切都是LOŚ͖̩͇̗̪̏̈́T ALL ISLOST他来了她来这里是为了我是他ICH或渗透埃斯阿尔我的FACE MY FACE ᵒh 上帝 no NO NOO̼奥恩θ 停止 t他*̶͑̾̾̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨe̠̅s ͎a̧͈͖r̽̾̈́͒͑e
not rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂Љ̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ş̳ TH̘Ë͖́̉ ͠P̯͍̭O̚N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎ş̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̮ ̝͍M̲̖͊̒ͪͩͬ̚̚͜ş̴̟̟͙̞ͩ͌͝
答案3
这与 sed 等效:
$ cat file9
<SubRecord1>
<Property Name=Name>My Main Search Keyword</Property>
<Property Name=Prompt>Dummy</Property>
<Property Name=Default>Value i'm Concerned to Modify</Property>
</SubRecord1>
<SubRecord2>
<Property Name=Name>My Main Search Keyword</Property>
<Property Name=Prompt>Dummy</Property>
<Property Name=Default>Do not Modify</Property>
</SubRecord2>
$ sed -r '/\bSubRecord1\b/!b;n;n;n;s/(<Property Name=Default>)(.*)(<\/Property>)/\1AAAA\3/' file9
<SubRecord1>
<Property Name=Name>My Main Search Keyword</Property>
<Property Name=Prompt>Dummy</Property>
<Property Name=Default>AAAA</Property>
</SubRecord1>
<SubRecord2>
<Property Name=Name>My Main Search Keyword</Property>
<Property Name=Prompt>Dummy</Property>
<Property Name=Default>Do not Modify</Property>
</SubRecord2>
使用字边界\b
可确保 sed 模式/SubRecord/
不会匹配SubRecord1
或SubRecord2