我需要以这种格式转换.txt文件的部分内容(首先匹配“SchDay”)
<SchDay>
<Name>School Occup WD</Name>
<Type>Fraction</Type>
<Hr index="0">0</Hr>
<Hr index="1">0</Hr>
<Hr index="2">0</Hr>
<Hr index="3">0</Hr>
<Hr index="4">0</Hr>
<Hr index="5">0</Hr>
<Hr index="6">0</Hr>
<Hr index="7">0.05</Hr>
<Hr index="8">0.75</Hr>
....
看起来像这样(值首先出现,“步骤”只需要定义2个结束点):
0.00, 0.00,
0.00, 6.00, <- end of step
0.05, 7.00,
0.75, 8.00,
...
等
这是我到目前为止所做的:
open (OUTFILE, ">C:/begperl/parts/all1.txt")|| die "Can't open it";
my @files = glob ("*.txt");
for (@files) {
open (INFILE, $_) || die "can't open infile";
@lines = <INFILE>;
my %answer;
$regex = '<SchDay';
for my $idx (0..$#lines) {
if ($lines[$idx] =~ /$regex/) {
for $ii (($idx + 3)..($idx + 26)){
{$answer{$ii} = ($lines[$ii]);}
}
}
foreach $key (sort keys %answer) { print OUTFILE "$answer{$key}\n" }
}
close (INFILE);}
所以我有我想要的台词。现在我需要提取数字,包括小数点,然后删除具有相同值的连续小时数。
答案 0 :(得分:1)
您的文档具有XML结构。通过使用适当的XML解析器,您可以更好地利用它。 XML::Twig允许您轻松隔离您感兴趣的XML文档的各个部分。在这种情况下,我们想要的只是在<Hr>
元素中出现的<SchDay>
元素:
my $parser = XML::Twig->new(
twig_roots => { 'SchDay/Hr' => \&do_print },
);
这只是告诉解析器为do_print
中的每个<Hr>
调用<SchDay>
子。将使用两个参数调用do_print
:我们刚刚创建的解析器实例和元素。使用$element->att('index')
访问index属性的值,使用$attr->text
获取属性的文本,然后格式化并打印它们。这是脚本:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $parser = XML::Twig->new(
twig_roots => { 'SchDay/Hr' => \&do_print },
);
$parser->parse(\*DATA);
sub do_print {
my $parser = shift;
my $element = shift;
printf "%.02f,%.02f,\n",
$element->text,
$element->att('index'),
;
$parser->purge;
return;
}
__DATA__
<SchDay>
<Name>School Occup WD</Name>
<Type>Fraction</Type>
<Hr index="0">0</Hr>
<Hr index="1">0</Hr>
<Hr index="2">0</Hr>
<Hr index="3">0</Hr>
<Hr index="4">0</Hr>
<Hr index="5">0</Hr>
<Hr index="6">0</Hr>
<Hr index="7">0.05</Hr>
<Hr index="8">0.75</Hr>
</SchDay>
输出:
0.00, 0.00, 0.00, 1.00, 0.00, 2.00, 0.00, 3.00, 0.00, 4.00, 0.00, 5.00, 0.00, 6.00, 0.05, 7.00, 0.75, 8.00,
至于需要用你的代码修复的内容......以下是一些我希望能帮你写出更好的Perl:
open (OUTFILE, ">C:/begperl/parts/all1.txt")|| die "Can't open it";
请勿使用OUTFILE
等裸字文件句柄。它们是包变量,这意味着它们可以在远处进行操作。相反,在最小的适用范围内声明一个词法变量,如:
my $filename = 'C:/begperl/parts/all1.txt';
open my $outfile, '>', $filename
or die "Failed to open '$filename': $!";
在for
循环中命名循环变量:
for my $input_file (@files) {
open my $input, '<', $input_file
or die "Failed to open '$input_file': $!";
当逐行处理时,不要啜饮。也就是说,请勿使用@lines = <INFILE>;
一次性读取文件的所有行。
请勿使用下面的3
和26
等神奇常量。相反,给他们起名字。例如:
use Const::Fast;
const my $HR_BEGIN => 3;
const my $HR_END => 26;
但是,这仍然太脆弱了。如果<Hr>
元素的行数发生变化怎么办?毕竟,这是一个XML文档,您可以轻松地使用
<Hr index="5">
0.00
</Hr>
那你做什么?