我有一个输入文本文件,如下所示:
DEV=T124^BRD=100^IO=HDMI^MODE=1^REG=ABC^FLD=X^VAL=200
DEV=T124^BRD=100^IO=HDMI^MODE=1^REG=ABC^FLD=Y^VAL=100
DEV=T124^BRD=100^IO=HDMI^MODE=2^REG=ABC^FLD=X^VAL=100
DEV=T124^BRD=100^IO=HDMI^MODE=2^REG=ABC^FLD=Y^VAL=200
DEV=T124^BRD=100^IO=DP^MODE=1^REG=XYZ^FLD=X^VAL=200
DEV=T124^BRD=100^IO=DP^MODE=1^REG=XYZ^FLD=Y^VAL=100
DEV=T124^BRD=100^IO=DP^MODE=1^REG=MLK^FLD=X^VAL=200
DEV=T124^BRD=100^IO=DP^MODE=1^REG=MLK^FLD=Y^VAL=100
我想解析它并将其输出到一个看起来像这样的文件:
DEV:T124
BRD:100
IO:HDMI
MODE:1
REG:ABC
FLD:X,VAL:200
FLD:Y,VAL:100
MODE:2
REG:ABC
FLD:X,VAL:100
FLD:Y,VAL:200
IO:DP
MODE:1
REG:XYZ
FLD:X,VAL:200
FLD:Y,VAL:100
REG:MLK
FLD:X,VAL:200
FLD:Y,VAL:100
我确实看过这个例子,但它并没有完全解决我的问题,因为Data:Dumper会将它打印成树形结构。 List of paths into hash array tree in Perl
另外,我是Perl的新手,并且不理解哈希的散列特别是在这个评论中: https://stackoverflow.com/a/13209256/3430142
我使用了该注释中发布的代码并编写了以下内容(@rows是一个包含输入文件中的行的数组)。
我不遵循foreach循环的工作方式。所以如果我将来需要改变它,我不知道该怎么做。这就是我要求替代实现的原因,我可以自定义/理解而不是依赖于该代码。
我使用了一些Dumper方法来编辑某些东西。我还用Tie来删除大括号和引号。
open TREE, "+>", $ARGV[1] or die $!;
my $tree = {"" => {}};
foreach my $input (@rows) {
chomp $input;
my $t = $tree;
$t = $t->{$_} //= {} for split /\^/ => $input;
}
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Varname = "PROD";
$Data::Dumper::Terse = 1;
$Data::Dumper::Purity = 1;
$Data::Dumper::Sparseseen = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Pair = "";
$Data::Dumper::Quotekeys = 1;
print TREE Dumper $tree;
close TREE;
tie @PST, 'Tie::File', $ARGV[1] or die $!;
for (@PST) {
s/[\{\},"]//g;
}
untie @PST;
输出如下:
DEV:T124
BRD:100
IO:HDMI
MODE:1
REG:ABC
FLD:X
VAL:200
FLD:Y
VAL:100
MODE:2
REG:ABC
FLD:X
VAL:100
FLD:Y
VAL:200
IO:DP
MODE:1
REG:XYZ
FLD:X
VAL:200
FLD:Y
VAL:100
REG:MLK
FLD:X
VAL:200
FLD:Y
VAL:100
正如你所看到的,我无法摆脱通过删除花括号创建的新行,而且我也无法获得我想要的结构,因为Dumper已经创建了预定义树。 / p>
感谢您的帮助。
答案 0 :(得分:0)
您不需要任何外部模块,甚至任何复杂的数据结构。你需要的只是数组。一个用于保存当前行的数据,另一个用于保存上一行的数据以进行比较。
以下脚本几乎可以展示您的需求,但您必须根据数据和输入/输出方法进行调整:
use strict;
use warnings;
my @prev;
while (<DATA>) {
chomp;
my @data = split;
for my $i (0..$#data) {
if (! $prev[$i] || $data[$i] ne $prev[$i]) {
@prev = ();
print '' . (' ' x $i) . $data[$i] . "\n";
}
}
@prev = @data;
}
__DATA__
step1a step2a step3a step4a step5a step6a
step1a step2a step3a step4a step5a step6b
step1a step2a step3a step4b step5a step6a
step1a step2a step3a step4b step5a step6b
step1a step2a step3b step4a step5b step6a
step1a step2a step3b step4a step5b step6b
step1a step2a step3b step4a step5c step6a
step1a step2a step3b step4a step5c step6b
输出
step1a
step2a
step3a
step4a
step5a
step6a
step6b
step4b
step5a
step6a
step6b
step3b
step4a
step5b
step6a
step6b
step5c
step6a
step6b
答案 1 :(得分:0)
如果您可以使用已排序的键,则在创建$tree
之后,以下内容将根据您创建哈希的方式主要执行您想要的操作:
dump_tree($tree);
sub dump_tree {
my ($hashR, $indent) = @_;
$indent ||= 0; # In case use warnings
foreach my $key (sort keys %$hashR) {
(my $print_key = $key) =~ s/=/:/;
print TREE ((' ' x $indent), "$print_key\n");
dump_tree($hashR->{$key}, $indent+2);
}
}
但是,它并没有像你的例子那样加倍同一行的FLD:,VAL:
。这应该是一个相对简单的补充,你可以在递归到dump_tree
之前检查你是否只有一个更深层次的单一密钥。