我的文件的最后几行/usr/share/glib-2.0/schemas/org.gnome.Vino.gschema.xml
:
<schemalist>
<schema>
<!-- some other tags -->
<key name='notify-on-connect' type='b'>
<summary>Notify on connect</summary>
<description>
If true, show a notification when a user connects to the system.
</description>
<default>true</default>
</key>
<key name='enabled' type='b'>
<summary>Enable remote access to the desktop</summary>
<description>
If true, allows remote access to the desktop via the RFB
protocol. Users on remote machines may then connect to the
desktop using a VNC viewer.
</description>
<default>false</default>
</key>
</schema>
</schemalist>
如果我想要grep
这一段:
<key name='enabled' type='b'>
<summary>Enable remote access to the desktop</summary>
<description>
If true, allows remote access to the desktop via the RFB
protocol. Users on remote machines may then connect to the
desktop using a VNC viewer.
</description>
<default>false</default>
</key>
我应该如何使用该grep
命令来实现这一目标?
答案1
由于您给出的示例是一个有效的 XML 文件,因此我将使用xq
XML 解析器工具来处理该文件,该工具是yq
安装包。
xq -x --xml-root key '
.schemalist.schema.key[] | select(."@name" == "enabled")
' infile.xml
如果“key”标签的“@name”属性等于“enabled”,则选择“key”标签。
来自xq -h
:
--xml-输出,-x
将 jq JSON 输出转码回 XML 并发出
--xml-根 XML_ROOT
当转码回 XML 时,将输出封装在具有此名称的元素中
答案2
由于您正在处理有效的 XML,因此您可以使用xmlstarlet
:
xmlstarlet sel -t -c "/schemalist/schema/key[@name='enabled']" infile.xml
这将查询 ( ) XML 文档并打印XPATH 元素的sel
副本,其中选择了属性设置为 的XML 节点。-c
/schemalist/schema/key
name
enabled
您的示例的输出:
<key name="enabled" type="b">
<summary>Enable remote access to the desktop</summary>
<description>
If true, allows remote access to the desktop via the RFB
protocol. Users on remote machines may then connect to the
desktop using a VNC viewer.
</description>
<default>false</default>
</key>
答案3
需要明确的是:
这很可能是某些能够理解 XML 文档的工具的工作,而不是grep
诸如此类的工具的工作。关于这一点有很好的答案。
也许:
grep
使用 perl-regexp 和其他补充。
grep -Pzo "(?s)\N*<key name='enabled'.*<\/key>\n" the_file.xml
或者有一点限制(不捕获前导空白):
grep -zo "<key name='enabled'.*<\/key>."
awk
awk '
/<key name='\''enabled'\''/ { p=1 }
p { print $0 }
p && /<\/key>/ { exit }
' the_file.xml
或者
awk "/<key name='enabled'/,/<\/key>/" the_file.xml
sed
sed -n '/<key name='\''enabled'\''/,/<\/key>/p' the_file.xml
答案4
获得所需输出的另一种方法是使用 XSL(可扩展样式表语言)xsltproc
- 如果您使用 GNOME 桌面,则默认安装该语言 - 将输入文档转换为所需文档(输出)。
这是样式表:
$ cat transform.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='xml' omit-xml-declaration='yes' />
<xsl:template match="/schemalist/schema/key[@name='enabled']">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match='text()|@*'/>
</xsl:stylesheet>
这是输出:
$ xsltproc transform.xsl input.xml
<key name="enabled" type="b">
<summary>Enable remote access to the desktop</summary>
<description>
If true, allows remote access to the desktop via the RFB
protocol. Users on remote machines may then connect to the
desktop using a VNC viewer.
</description>
<default>false</default>
</key>
$