unix脚本,用于计算特定xml标记之间的字符数

时间:2010-09-21 07:56:50

标签: xml unix grep

您好我正在尝试创建一个脚本,在返回变体之前,将根据这些值计算xml标记和idealy组之间的字符数:

例如

<CONTEXT_1>aaaa<CONTEXT_1>
<CONTEXT_2>bb<CONTEXT_2>
<CONTEXT_2>dfgh<CONTEXT_2>
<CONTEXT_6>bb<CONTEXT_6>
<CONTEXT_1>bbbb<CONTEXT_1>

结果将是

<CONTEXT_1> 4
<CONTEXT_2> 2,4
<CONTEXT_6> 4

任何帮助将不胜感激!我完全被困了

由于 中号

5 个答案:

答案 0 :(得分:1)

1。使用特定于XML的实用程序

我认为任何用于处理XML的命令行工具都比自定义awk / sed hacks更好。使用这些工具的脚本更加健壮,并且在XML输入稍微重新格式化时不会中断(例如,换行符在哪里以及文档缩进的方式无关紧要)。我从命令行查询XML的工具是xmlstarlet

2。修复XML

然后,您需要修复XML:正确关闭标记并添加根元素。像这样:

<root>
<CONTEXT_1>aaaa</CONTEXT_1>
<CONTEXT_2>bb</CONTEXT_2>
<CONTEXT_2>dfgh</CONTEXT_2>
<CONTEXT_6>bb</CONTEXT_6>
<CONTEXT_1>bbbb</CONTEXT_1>
</root>

3。使用XPath和XSLT

使用XPath选择所需的元素,并使用XSLT表达式处理它们。在您的示例中,您可以使用

计算元素的长度
$ xmlstarlet sel -t -m '//root/*' -v "name(.)" -o ": " -v "string-length(.)" -n test.xml 

//root/*选择root的所有子节点。 name(.)打印当前所选元素的元素名称,string-length(.)打印其内容的长度。

获得输出:

CONTEXT_1: 4
CONTEXT_2: 2
CONTEXT_2: 4
CONTEXT_6: 2
CONTEXT_1: 4

使用awk或类似工具随意分组结果。

答案 1 :(得分:0)

这是Awk的一项工作:一种功能齐全的文本处理语言。

像(未经测试)的东西:

awk \
"BEGIN { $INIT_TAB_AWK } \
{ split(\$0, tab, \"\"); \
for (chara in tab) \
{ for (chara2 in tab_search) \
{ if (tab_search[chara2] == tab[chara]) { final_tab[chara2]++ } } } } \
END { for (chara in final_tab) \
{ print tab_search[chara] \" => \" final_tab[chara] } }"

答案 2 :(得分:0)

您可以使用sed执行此类操作:

sed  's/^<\([^>]*\)>\(.*\)<.*$/\1 \2/g' file.xml | sort | while read line
do
    context=`echo $line | cut -d' ' -f1`
    count=`echo $line | cut -d' ' -f2 | tr -d '\n' | wc -c`
    echo $context: $count
done | uniq

打印:

CONTEXT_1: 4
CONTEXT_2: 2
CONTEXT_2: 4
CONTEXT_6: 2

答案 3 :(得分:0)

使用Perl:

#! /bin/perl    
open FILE, $ARGV[0] or die $!;
while (my $line = <FILE>) {
        if ($line =~ /^<([^>]*)>(.*)<.*$/) {
            $table{$1}="$table{$1},".length($2);
         }
}    
foreach my $key (sort keys %table) {
  print "$key ".substr($table{$key},1)."\n";
}

输出是:

CONTEXT_1 4,4
CONTEXT_2 2,4
CONTEXT_6 2

答案 4 :(得分:-1)

$ awk -F">" '{sub("<.*","",$2);a[$1]=a[$1]","length($2)}END{for (i in a) print i,a[i]}' file
<CONTEXT_6 ,2
<CONTEXT_1 ,4,4
<CONTEXT_2 ,2,4