我正在尝试按<Description>
数字分割Bit
文字,并将Bit
数字元素放入其中。这是文件,我正在解析。
<Register>
<Name>abc</Name>
<Abstract></Abstract>
<Description>Bit 6 random description
Bit 5 msg octet 2
Bit 4-1
Bit 0 msg octet 4
These registers containpart of the Upstream Message.
They should be written only after the cleared by hardware.
</Description>
<Field>
<Name>qwe</Name>
<Description></Description>
<BitFieldOffset>6</BitFieldOffset>
<Size>1</Size>
<AccessMode>Read/Write</AccessMode>
</Field>
<Field>
<Name>qwe</Name>
<Description></Description>
<BitFieldOffset>5</BitFieldOffset>
<Size>1</Size>
<AccessMode>Read/Write</AccessMode>
</Field>
<Field>
....
</Field>
</Register>
<Register>
<Name>xyz</Name>
<Abstract></Abstract>
<Description>Bit 3 msg octet 1
Bit 2 msg octet 2
Bit 1 msg octet 3
Bit 0 msg octet 4
These registers.
They should be written only after the cleared by hardware.
</Description>
<Field>
....
</Field>
<Field>
....
</Field>
</Register>
预期输出为:
Expected output:
<Register>
<long_description>
These registers containpart of the Upstream Message.
They should be written only after the cleared by hardware.
</long_description>
<bit_field position="6" width=" 1">
<long_description>
<p> random description</p>
</long_description>
<bit_field position="5" width=" 1">
<long_description>
<p>...</p>
</long_description>
<bit_field position="1" width=" 4">
<long_description>
<p>...</p>
</long_description>
</Register>
<Register>
.
.
.
</Register>
我正在使用XML-Twig包来解析这个文件,但却陷入了分裂。
foreach my $register ( $twig->get_xpath('//Register') ) # get each <Register>
{
my $reg_description= $register->first_child('Description')->text;
.
.
.
foreach my $xml_field ($register->get_xpath('Field'))
{
.
.
my @matched = split ('Bit\s+[0-9]', $reg_description);
.
.
}
}
我不知道如何相应地创建<bit_field>
并将Bit
以外的文字保存到<Register> <long_description>
。有人可以帮忙吗?
编辑:
Bit
中的<Description>
可以有多行。例如,在以下示例中,Bit 10-9
的描述直到Bit 8
<Description>Bit 11 GOOF
Bit 10-9 Clk Selection:
00 : 8 MHz
01 : 4 MHz
10 : 2 MHz
11 : 1 MHz
Bit 8 Clk Enable : 1 = Enable CLK
<Description>
答案 0 :(得分:1)
如果我把一切都搞定了,你可以逐行查看整个文本块。
使用正则表达式检查一行是否与某个模式匹配。捕获相关部分。在包含存储每个位的详细信息的哈希的数组中逐位缓存。
不包含位模式的缓冲行。如果跟随另一行,包含位模式,则缓冲区必须属于最近的位。将它附加到那里。所有其他行必须是整体描述的一部分。 注意:这并不区分最后一位描述的任何其他行。如果有这么一点,它的附加行将成为整体描述的开始。 (但是你说你的数据中没有这些东西。)
概念证明:
#!/usr/bin/perl
use strict;
use warnings;
my $description_in = 'Bit 6 random description
Bla bla additional line bla bla
bla bla
Bit 5 msg octet 2
Empty line below
Bla bla set to gain instant world domination bla bla
Bit 4-1
Bit 0 msg octet 4
These registers containpart of the Upstream Message.
They should be written only after the cleared by hardware.
Empty line above
Bla bla bla...';
my @bits = ();
my $description_overall = '';
my $line_buffer = '';
foreach my $line (split("\n", $description_in)) {
# if line
# begins with optional white spaces
# followed by "Bit"
# followed by at least one white space
# followed by at least one digit (we capture the digits)
# followed by an optional sequence of optional white spaces, "-", optional white spaces and at least one digit (we capture the digits)
# followed by an optional sequence of at least one white space and any characters (we capture the characters)
# followed by the end of the line
if ($line =~ m/^\s*Bit\s+(\d+)(?:\s*-\s*(\d+))?(?:\s+(.*?))?$/) {
my ($position_begin, $position_end, $description) = ($1, $2, $3);
my $width;
# if there already are bits we've processed
if (scalar(@bits)) {
# the lines possibly buffered belong to the bit before the current one, so append them to its description
$bits[$#bits]->{description} .= (length($bits[$#bits]->{description}) ? "\n" : '') . $line_buffer;
# and reset the line buffer to collect the additional lines of the current bit;
$line_buffer = '';
}
# $position_end is defined only if it was a "Bit n-m"
# otherwise set it to $position_begin
$position_end = defined($position_end) ? $position_end : $position_begin;
$width = abs($position_end - $position_begin) + 1;
# set description to the empty string if not defined (i.e. no description was found)
$description = defined($description) ? $description : '';
# push a ref to a new hash with the keys position, description and width into the list of bits
push(@bits, { position => (sort({$a <=> $b} ($position_begin, $position_end)))[0], # always take the lower position
description => $description,
width => $width });
}
else {
# it's not a bit pattern, so just buffer the line
$line_buffer .= (length($line_buffer) ? "\n" : '') . $line;
}
}
# anything still in the buffer must belong to the overall description
$description_overall .= $line_buffer;
print("<Register>\n <long_description>\n$description_overall\n </long_description>\n");
foreach my $bit (@bits) {
print(" <bit_field position=\"$bit->{position}\" width=\"$bit->{width}\">\n <long_description>\n$bit->{description}\n </long_description>\n </bit_field>\n")
}
print("</Register>\n");
打印:
<Register>
<long_description>
These registers containpart of the Upstream Message.
They should be written only after the cleared by hardware.
Empty line above
Bla bla bla...
</long_description>
<bit_field position="6" width="1">
<long_description>
random description
Bla bla additional line bla bla
bla bla
</long_description>
</bit_field>
<bit_field position="5" width="1">
<long_description>
msg octet 2
Empty line below
Bla bla set to gain instant world domination bla bla
</long_description>
</bit_field>
<bit_field position="1" width="4">
<long_description>
</long_description>
</bit_field>
<bit_field position="0" width="1">
<long_description>
msg octet 4
</long_description>
</bit_field>
</Register>
我把它写成独立脚本,以便我可以测试它。您必须将其改编为您的脚本。
可能会添加一些整体描述的处理,消除那些长白色空间序列。
首先,我尝试使用连续模式(while ($x =~ m/^...$/gc)
)但是以某种方式吃掉了行结尾,导致只匹配每一行。为了使它们远离实际匹配,看起来没有用(说它没有实现;我想,我必须在这台计算机上检查我的Perl?),所以显式拆分线条是一种解决方法。
也可以使用grep()
s,map()
等缩短它。但我认为,冗长的版本更好地展示了这些想法。所以我甚至没有调查过。