我有一个包含以下内容的XML文件:
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
我需要一种方法来提取 <job..>
和 </job>
标签中的内容,在这种情况下是 programmin。这应该在 Linux 命令提示符下使用 grep/sed/awk 完成。你真的必须只使用那些工具吗? 它们不是为XML处理而设计的,虽然可能会获得正常运行的东西,但在极限情况下(如编码、换行符等)会失败。
我建议使用xml_grep:
xml_grep 'job' jobs.xml --text_only
这将输出:
programming
在Ubuntu/Debian上,xml_grep位于xml-twig-tools软件包中。
grep '<job' file_name | cut -f2 -d">"|cut -f1 -d"<"
使用xmlstarlet:
echo '<job xmlns="http://www.sample.com/">programming</job>' | \
xmlstarlet sel -N var="http://www.sample.com/" -t -m "//var:job" -v '.'
xmlstarlet
只是其中之一。其他工具包括xmllint
、xpath
等。请参考https://dev59.com/FmUp5IYBdhLWcg3wLVOn。 - tripleee<root>
<sometag val1="fish" val2="carrot" val3="narf"></sometag>
</root>
<root>
<sometag
val1="fish"
val2="carrot"
val3="narf"></sometag>
</root>
<root
><sometag
val1="fish"
val2="carrot"
val3="narf"
></sometag></root>
<root><sometag val1="fish" val2="carrot" val3="narf"/></root>
E.g.:
xml_grep 'job' jobs.xml --text_only
然而,为了提供更好的答案,以下是一些基于您的源数据自行创建的示例:
第一种方法:
使用 twig 处理程序
捕获特定类型的元素并对其进行操作。这种方式的优点是它在解析 XML 时“随时随地”进行,如果需要,可以在运行时修改它。当您处理大文件并使用 purge
或 flush
时,这对于丢弃“已处理”的 XML 特别有用:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new(
twig_handlers => {
'job' => sub { print $_ ->text }
}
)->parse( <> );
<>
来获取输入(通过管道或命令行指定./myscript somefile.xml
),并处理每个job
元素,提取和打印相关文本。您可能需要使用print $_ -> text,"\n"
来插入换行符。由于它匹配了“job”元素,因此也会匹配嵌套的工作元素。<job>programming
<job>anotherjob</job>
</job>
这段代码会匹配两次,但是输出的一部分也会重复。如果您喜欢,也可以使用 /job
进行匹配。这样可以方便地打印和删除元素,或者复制并粘贴一个修改过的 XML 结构。
另一种方法是先解析,然后根据结构“打印”:
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> root -> text;
job
只需要打印其文本内容即可。job
或 /job
并专门打印它们的内容。my $twig = XML::Twig->new( )->parse( <> );
print $twig -> findnodes('/job',0)->text;
XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( <> ) -> print;
有各种输出格式选项,但对于简单的XML(如您的),大多数选项看起来相似。
$ cat file
test
<job xmlns="http://www.sample.com/">programming</job>
<job xmlns="http://www.sample.com/">
programming</job>
$ awk -vRS="</job>" '{gsub(/.*<job.*>/,"");print}' file
programming
programming
</job>
是有效的,但是你的脚本无法识别它。<!-- </job> -->
是需要被忽略的注释(而 <!CDATA[[ </job> ]]>
则是字面数据),但是你的脚本不知道这些。还有一些情况,比如有一个 DTD 定义了新的宏,使得 &foo;
扩展为本地指定的内容,以及简单的情况,比如需要将 &
转换为 &
。试图自己编写 XML 解析(或更糟糕的是生成)会导致无数的边角情况和需要逐个修复的细节问题。 - Charles Duffy$ cat file.xml
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
$ cat file.xml | sed -ne '/<heading>/s#\s*<[^>]*>\s*##gp'
Reminder
解释:
cat file.xml | sed -ne '/<pattern_to_find>/s#\s*<[^>]*>\s*##gp'
n
- 抑制打印所有行
e
- 脚本
/<pattern_to_find>/
- 查找包含指定模式的行,例如<heading>
接下来是替换部分 s///p
,它删除除所需值外的所有内容,其中将/
替换为#
以提高可读性:
s#\s*<[^>]*>\s*##gp
\s*
- 包括存在的空格(结尾相同)
<[^>]*>
表示<xml_tag>
作为非贪婪regex替代方案,因为<.*?>
在sed中不起作用
g - 替换所有内容,例如关闭xml</xml_tag>
标记
sed -ne '/<\/job>/ { s/<[^>]*>\(.*\)<\/job>/\1/; p }'
注意: -n
停止自动输出所有内容;-e
表示它是一个一行命令(而不是脚本);/<\/job>
的作用类似于 grep 命令;s
剥离开标签和属性以及结束标签;;
是一个新语句的开始;p
打印;{}
使 grep 命令应用于两个语句,作为一个整体。
$ cat file.xml
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
<job xmlns="http://www.sample.com/">designing</job>
<job xmlns="http://www.sample.com/">managing</job>
<job xmlns="http://www.sample.com/">teaching</job>
path
参数指定要剪切的元素路径。在这种情况下,由于我们不关心标签,因此将标签重命名为\n
,以便我们得到一个漂亮的列表:
$ xmlcutty -path /job -rename '\n' file.xml
programming
designing
managing
teaching
这样怎么样:
cat a.xml | grep '<job' | cut -d '>' -f 2 | cut -d '<' -f 1
grep '<job' a.xml | ...
- ghostdog74< a.xml | grep ...
,那么你会更接近开头。 - Thoryourxmlfile.xml
<item>
<title>15:54:57 - George:</title>
<description>Diane DeConn? You saw Diane DeConn!</description>
</item>
<item>
<title>15:55:17 - Jerry:</title>
<description>Something huh?</description>
</item>
在你的xml文件中使用grep 'title'
<title>15:54:57 - George:</title>
<title>15:55:17 - Jerry:</title>
在你的xml文件中使用grep 'title'命令 | awk -F">" '{print $2}'
15:54:57 - George:</title
15:55:17 - Jerry:</title
grep 'title' yourxmlfile.xml | awk -F">" '{print $2}' | awk -F"<" '{print $1}'
在编程中,上述代码是用于从XML文件中提取标题的命令。它使用grep命令查找包含“title”的行,然后使用awk命令分割字符串并提取所需的文本。
15:54:57 - George:
15:55:17 - Jerry:
s/&/\&/g
,同样适用于"
等,当然这不适用于用户定义的实体等。 - 13ren