查找包含特定标签名称的 xml 文件并打印标签名称之间的单词

查找包含特定标签名称的 xml 文件并打印标签名称之间的单词

我们可以找到如下的xml文件类型

find /tmp/ -type f -name '*.xml'

但如何更改语法以便仅查找包含以下内容的 xml:

<Name>some words</Name>

并打印之间的内容:

<Name> ------ </Name>

预期产出

some words      

示例 - xml 文件包含:

<Name>files_with_extra_data</Name>

预期产出

files_with_extra_data

答案1

一个简单的解决方案是使用 sed:

find /tmp -name '*.xml' -exec sed -n 's/<Name>\([^<]*\)<\/Name>/\1/p' {} +

正则表达式匹配标签并打印之间的内容。如果我们删除转义字符就更容易阅读:

s / <Name>([^<]*)</Name> / \1 

括号匹配任何非“<”的字符并映射到 \1

正如评论中提到的,这将是一个简单的解决方案,正则表达式无法应对结构化文本的所有可能变化。因此,如果标签或其他标签之间有多行,它将无法工作,您将需要使用真正的 xml 解析器

答案2

对于像这样的简单 XML 作业,我会使用XML2cut。 (或sed,或awk,或perl)。

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | grep '/Name=' |
  cut -d '=' -f2-

或者

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | sed -n -e 's/^[^=]*\/Name=//p'

或者

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; | 
  awk -F'=' '/Name=/ {$1=""; sub(/^ /,"",$0); print }'

sub()awk 版本中的函数调用会去除将 $1 设置为 "" 后留下的前导空格 - awk 无法从输入行中删除字段,您能做的最好的是将其设置为空字符串并清理或者,split()将行放入数组中,删除不需要的字段,然后将数组连接到字符串中进行打印,因为 awk没有join()这样的函数perl,所以您必须编写自己的函数。 )

或者

find . -iname '*.xml' -exec bash -c 'xml2 < {}' \; |
  perl -F= -lane 'if (m:/Name=:) { delete @F[0]; print @F}'

xml2将 XML 格式的数据转换为适合使用面向行的文本实用程序(如awk、 or sed、 orperl等​​)进行处理的面向行的格式。它附带了一个相应的2xml程序,可以将面向行的格式转换回正确格式的 XML。

对于更复杂的任务,我会使用xmlstarlet

xmlstarlet是一种 XML 处理工具,可用于列出、查询、提取和修改 XML 文件中的数据。

两者都可以为 debian 和其他 Linux 发行版打包。


在我看来,最好的解决方案是使用类似perlpython具有 XML 解析库的语言,并使用它。 xmlstarlet非常适合在 shell 中处理 XML 文件,但是为非常复杂的搜索构建命令行比仅仅编写脚本perlpython完成这项工作变得更多工作(并且更难以阅读和调试)。部分原因是我用这些语言进行了更多编程,并且发现它更容易使用......但主要是因为在我看来,最好将学习精力集中在可用于各种任务的通用语言上,而不是特定于领域的语言/工具只能用于一件非常特定的事情。

答案3

pcregrep

pcregrep -rMh --include='\.xml\z' -o1 '(?s)<name>(.*?)</name>' .

答案4

sed -n '/Name/{s/.*<Name>//;s/<\/Name.*//;p;}' "$FULL_XML_PATH"

相关内容