如何使用 awk、grep 和/或 powershell 过滤多行

如何使用 awk、grep 和/或 powershell 过滤多行

我的情况是我有一个文件,其内容如下所示,但更长。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就足够了:gamename

xmlstarlet ed -d '//game[not(contains(@name, "(USA)"))]' file-orig.xml >file-new.xml

这将删除节点属性(USA)中不包含的所有游戏。namegame

删除所有非标题后,我下载的文件将包含 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

相关内容