我的情况是我有一个文件,其内容如下所示,但更长。https://pastebin.com/q33wFdAX
我需要删除每个出现的
<category>Games</category>
</game>
如果类别中有数据,我们不想删除它。所以基本上,如果我可以像 grep -v 一样精确匹配这个双行并反转,那么我可以输出到一个没有这些行的新文件。
我将拥有的不仅仅是这个类别,因此我需要能够使用多个 or 语句。我在记事本++中使用的正则表达式示例来手动完成此操作
(^\s+<category>Games</category>\s+</game>$|^\s+<category>Applications</category>\s+</game>$)
如果你能给我一个在 powershell 中执行此操作的简单方法,那就加分了,我希望能够在任一操作系统上执行此操作。我不太擅长高级正则表达式、awk 等。
答案1
给定这原来的文件,以下将删除(USA)
标题节点rom
属性中未提及的所有标题name
:
xmlstarlet ed -d '//game[not(contains(rom/@name, "(USA)"))]' file-orig.xml >file-new.xml
XPath 表达式//game[not(contains(rom/@name, "(USA)"))]
选择game
至少有一个rom
子节点的所有节点,该子节点具有name
以下属性:不是包含字符串(USA)
.这些被选择用于删除。
使用命令行上的重定向将输出写入新文件。
在短暂查看 XML 数据之后,我注意到,不需要查看节点,只需查看主节点的属性rom
就足够了:game
name
xmlstarlet ed -d '//game[not(contains(@name, "(USA)"))]' file-orig.xml >file-new.xml
这将删除节点属性(USA)
中不包含的所有游戏。name
game
删除所有非标题后,我下载的文件将包含 1979 个标题(USA)
。
要另外过滤掉所有非Games
类别:
xmlstarlet ed \
-d '//game[not(contains(@name, "(USA)"))]' \
-d '//game[category != "Games"]' file-orig.xml >file-new.xml
剩下 1474 个游戏标题。
只是为了好玩,按游戏标题总数对游戏标题进行排序尺寸:
xmlstarlet ed \
-d '//game[not(contains(@name, "(USA)"))]' \
-d '//game[category != "Games"]' file-orig.xml |
xmlstarlet sel -t -m '//game' \
-v 'sum(rom/@size)' -o ' ' -v '@name' -nl | sort -n