我需要一个脚本来递归遍历目录,并按照最频繁到最不频繁的顺序解析每个.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;
但是我在定义$ bucket变量时遇到了问题,这个脚本是用来定义桶的
$bucket = "monkey | tree | banana"
,输出就像
word monkey occurs 4 times
word monkey occurs 3 times
word monkey occurs 1 times
在我的情况下,我必须使用通配符,因此它会解析介于两者之间的所有内容&lt;&gt;像
$bucket = <"<*"."*>">;
但这会创建一个包含所有xml代码的输出文件,并计算每个&#34;&lt;&#34;和&#34;&gt;&#34;添加了toguether和输出
occurs 50 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
解决:
#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;
输出
<Default Extension="xlsx" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/> occurs 1 times
<Default Extension="png" ContentType="image/png"/> occurs 1 times
<Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/> occurs 1 times
谢谢大家的帮助,这真的很有帮助,对于他在我编辑的博客上的代码来说,这是一个非常有用的
http://perlgems.blogspot.pt/2012/05/normal-0-false-false-false-en-us-x-none_2673.html
答案 0 :(得分:3)
只是用一种用于查询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处理器,对于此示例,我将提出开源软件BaseX;你也可以使用所有其他XQuery引擎。确保安装它,以便您也拥有命令行包装器;通过下载和安装或使用Debian和Ubuntu中的“basex”软件包。
将上面的脚本存储在一个文件中,此处为test.xq
,并调用use find
为当前文件夹中的每个XML文件调用它:
find . -name "*.xml" -exec basex -i {} test.xq \;
它将打印每个文件的统计信息。
答案 1 :(得分:2)
使用xml2的Oneliner:
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
示例输出:
48376 id
16125 username
16125 title
16125 timestamp
16125 sha1
16125 ns
16106 text
14711 page
10436 comment
8032 minor
4978 data
4977 track
4977 timecode
4455 BlockGroup
2262 ReferenceBlock
1414 sitename
1414 namespace
1414 generator
1414 case
1414 base
385 SimpleBlock
142 discardable
137 Timecode
130 Cluster
126 keyframe
40 !
38 name
28 TrackType
...
更新:
Variant“提取&lt;和&gt;之间的所有内容”,但仍使用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
示例输出:
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"
...
更新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
输出:
4 <r/>
3 <w/>
2 <w tag="22"/>
1 <?xml version="1.0"?/>
1 <w tag="11"/>
1 <q/>
1 <ololo/>
这是你想要的吗?
答案 2 :(得分:0)
对于您提供的输入(没有有效的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 />
您可以使用基本的unix工具:
$ sort <input.txt |uniq -c
这将返回:
3 <tag1 This is tag1 />
3 <tag2 This is tag2 />
1 <tag3 This is tag3 />