用于解析.xml文件和列表标记的脚本
我需要一个脚本递归地遍历一个目录,解析每个用于解析.xml文件和列表标记的脚本,xml,list,parsing,Xml,List,Parsing,我需要一个脚本递归地遍历一个目录,解析每个.xml文件,并按从最频繁到较不频繁的顺序列出标记,告诉每个标记出现多少次,以便统计哪些标记是最常用的 我在考虑Perl,但如果您认为有更好的方法,请告诉我 我能够找到一个perl脚本来计算文档中的单词 sub by_count { $count{$b} <=> $count{$a}; } open(INPUT, "<[Content_Types].xml"); open(OUTPUT, ">output"); $buck
.xml
文件,并按从最频繁到较不频繁的顺序列出标记,告诉每个标记出现多少次,以便统计哪些标记是最常用的
我在考虑Perl,但如果您认为有更好的方法,请告诉我
我能够找到一个perl脚本来计算文档中的单词
sub by_count {
$count{$b} <=> $count{$a};
}
open(INPUT, "<[Content_Types].xml");
open(OUTPUT, ">output");
$bucket = "";
while(<INPUT>){
@words = split(/\s+/);
foreach $word (@words){
if($word=~/($bucket)/io){
print OUTPUT "$word\n";
$count{$1}++;}
}
}
foreach $word (sort by_count keys %count) {
print OUTPUT "$word occurs $count{$word} times\n";
}
close INPUT;
close OUTPUT;
结果是
word monkey occurs 4 times
word monkey occurs 3 times
word monkey occurs 1 times
在我的例子中,我必须使用通配符,这样它将解析中间的所有内容,比如
我需要做以下事情:
示例.xml文档:
<tag1 This is tag1 />
<tag1 This is tag1 />
<tag2 This is tag2 />
<tag2 This is tag2 />
<tag1 This is tag1 />
<tag2 This is tag2 />
<tag3 This is tag3 />
输出:
<tag1 This is tag1 /> appears 2 times
<tag2 This is tag2 /> appears 3 times
<tag3 This is tag3 /> appears 1 time
出现2次
出现3次
出现1次
已解决:
#usr/bin/perl
sub by_count {
$count{$b} <=> $count{$a};
}
open(INPUT, "</file.xml"); #xml file
open(OUTPUT, ">outputfile"); #Create an output file
$bucket = qw/./;
while(<INPUT>){
@words = split(/\</); #Whenever reaches a '<' breaks the string
foreach $word (@words){
if($word=~/($bucket*>)/io){
#print OUTPUT "$word";
#print OUTPUT "\n\n";
$count{$1}++;}
}
}
foreach $word (sort by_count keys %count) {
print OUTPUT "<$word occurs $count{$word} times\n\n";
}
close INPUT;
close OUTPUT;
#usr/bin/perl
按单位计数{
$count{$b}$count{$a};
}
打开(输入,“输出文件”)#创建一个输出文件
$bucket=qw/;
while(){
@words=split(/\)/io){
#打印输出“$word”;
#打印输出“\n\n”;
$count{$1}++;}
}
}
foreach$word(按\u计数键%count排序){
打印输出“仅举一个用于查询XML文件的语言示例,XQuery:
for $element in //*
let $name := $element/local-name()
group by $name
order by count($element) descending
return concat($name, ": ", count($element))
如何将此应用于多个XML文档取决于您使用的查询处理器,根据您的需要,您可以在XQuery中执行此操作,也可以使用find或其他方法调用每个文件的脚本
要执行,您需要一个XQuery处理器,在本例中,我将推荐开源软件;您也可以使用所有其他XQuery引擎。请确保安装它,这样您也可以使用命令行包装器;或者下载并安装,或者使用Debian和Ubuntu中的“basex”包
将上面的脚本存储在一个文件中,在这里test.xq
,然后调用usefind
为当前文件夹中的每个XML文件调用它:
find . -name "*.xml" -exec basex -i {} test.xq \;
它将打印每个文件的统计信息。Oneliner使用xml2:
find . -type f -name '*.xml' -print0 | \
xargs -0 -n 1 sh -c 'xml2 < "$0"' | \
grep -v '/@' | cut -d= -f 1 | uniq | grep -o '[^/]\+$' | \
sort | uniq -c | sort -rn
更新:
“提取<和>”之间的所有内容,但仍使用xml2正确处理XML的变体:
find . -type f -name '*.xml' -print0 | xargs -0 -n 1 sh -c 'xml2 < "$0"' | sed 's!^\([^@=]*\)=.*!\1=!' | 2xml | sed 's!>!>\n!g' | grep -v '^</' | sed 's!^<!!; s!/\?>!!;' | sort | uniq -c | sort -rn
更新2另一次尝试了解您想要什么:
我的输入示例:
<q>
<w tag="11"/>
<w tag="22"/>
<r/>
<r/>
<w tag="22"/>
<w/>
<w/>
<w>ignore me
</w>
<r />
<ololo>
<r />
<!--
<w tag="33"/>
-->
</ololo>
</q>
别理我
脚本:
cat q.xml | xml2 | sed 's!^\([^@=]*\)=.*!\1=!' | grep -v '/!=' | 2xml | xmllint -format - | sed 's/^\s*//g' | grep -v '^</\|^$' | sed 's!/\?>$!/>!' | sort | uniq -c | sort -rn
cat q.xml | xml2 | sed's!^\([^@=]*\)=.!\1=!'| grep-v'/!='| 2xml | xmllint-format-| sed's/^\s*///g'| grep-v'^$!/>| sort | uniq-c | sort-rn
输出:
4 <r/>
3 <w/>
2 <w tag="22"/>
1 <?xml version="1.0"?/>
1 <w tag="11"/>
1 <q/>
1 <ololo/>
4
3.
2.
1.
1.
1.
1.
它是否与您想要的类似?对于您提供的输入(它不是有效的XML)
您可以使用基本的unix工具:
$ sort <input.txt |uniq -c
$sort我会使用Perl,但这主要是我个人的偏好,我不会为您编写整个程序。CPAN上并不缺少XML库。您尝试了什么?遇到了什么问题?我实际上是Perl新手,有点不知所措。我仍在试图找出实现这一点的逻辑,只有到那时我才知道我将能够在代码中转换它。我已经做了一个按文件名列出并计算重复次数的操作,但我也指定了名称。在这里,我不知道我将找到多少不同的标记,因此我需要找到一种方法来打印遇到的每个标记,说出“”之间的所有内容,并打印出我正在考虑使用的标记的出现频率glob函数。你认为呢?XML不是一种常规语言,你不能使用正则表达式解析它——至少在没有关于文件结构限制的专门知识的情况下是这样。如果你想使用perl,可以使用一些XML SAX库,在开始标记上添加一个侦听器,并在每次该侦听器获得cal时在其名称上的哈希中增加一个计数器led。是的,但我认为我可以像解析普通文本一样解析它,过滤介于“”之间的所有内容。这不起作用吗?谢谢Jens Erat,但我该如何运行该脚本?用一个小示例扩展了我的答案。我敢打赌,在正确解析XML时,Perl将无法在6行合理的代码中完成这项工作。我应该替换test.xq脚本中的任何内容吗?我在ubuntu fork中使用sudo-apt-get-install-baseX安装了baseX,并且安装了它。但是当我运行find.-name“*.xml”-exec-baseX-I{}test.xq\;命令时,我得到了一个错误:[警告]/usr/bin/basex:无法在/usr/share/javas中找到/usr/share/java/tagsoup.jar。不知道为什么它想在未安装的情况下使用tagsoup。最简单的方法是安装推荐的包libtagsoup java
。我应该如何运行它?抱歉,我是linux的新手,正在编程将所有四行复制并粘贴到命令line,就像你对我的一个所做的那样。谢谢它工作正常,但是是否仍然可以列出 之间的整行?要查看属性,可以删除grep-v'/@
chunk。属性howewer将不会与其元素相关联。更新了将元素绑定到属性的解决方案。虽然没有完全测试,但脚本可以修改我可以排除一些属性,或者只使用属性名(而不是值)。非常感谢Jens Erat,但我已经弄明白了关于如何使其递归的任何建议?我有一个包含多个子目录的目录,所有这些目录中都有一个[Content_Type].xml文件。我想让脚本解析这些文件中的每一个。开始学习您正在使用的工具。您需要使用find
做完全相同的事情。我现在为其中两个答案提出了建议,请阅读man find
了解如何使用它,如果您自己付出了努力但没有成功,请随时提出新问题,可能是这一部分在哪里更合适(不是关于编程,而是关于使用程序)。好的,我会接受你的建议,非常感谢。很抱歉,我是一个新手,但我刚刚开始实习,以前从未编程过。
find . -type f -name '*.xml' -print0 | xargs -0 -n 1 sh -c 'xml2 < "$0"' | sed 's!^\([^@=]*\)=.*!\1=!' | 2xml | sed 's!>!>\n!g' | grep -v '^</' | sed 's!^<!!; s!/\?>!!;' | sort | uniq -c | sort -rn
4986 id
1662 username
1662 title
1662 timestamp
1662 sha1
1662 revision
1662 page
1662 ns
1662 contributor
1303 comment
631 minor
170 text xml:space="preserve" bytes="72"
84 sitename
84 siteinfo
84 namespaces
84 namespace key="9" case="first-letter"
84 namespace key="8" case="first-letter"
84 namespace key="7" case="first-letter"
84 namespace key="6" case="first-letter"
84 namespace key="5" case="first-letter"
...
<q>
<w tag="11"/>
<w tag="22"/>
<r/>
<r/>
<w tag="22"/>
<w/>
<w/>
<w>ignore me
</w>
<r />
<ololo>
<r />
<!--
<w tag="33"/>
-->
</ololo>
</q>
cat q.xml | xml2 | sed 's!^\([^@=]*\)=.*!\1=!' | grep -v '/!=' | 2xml | xmllint -format - | sed 's/^\s*//g' | grep -v '^</\|^$' | sed 's!/\?>$!/>!' | sort | uniq -c | sort -rn
4 <r/>
3 <w/>
2 <w tag="22"/>
1 <?xml version="1.0"?/>
1 <w tag="11"/>
1 <q/>
1 <ololo/>
<tag1 This is tag1 />
<tag1 This is tag1 />
<tag2 This is tag2 />
<tag2 This is tag2 />
<tag1 This is tag1 />
<tag2 This is tag2 />
<tag3 This is tag3 />
$ sort <input.txt |uniq -c
3 <tag1 This is tag1 />
3 <tag2 This is tag2 />
1 <tag3 This is tag3 />