Perl专家 - 我试图解决我的问题是变成了很多代码,在PERL中似乎我正在接近这个问题。这是我的问题:
我有一个文本块(下面的例子),它可以在列数据之间有可变数量的空格。我使用的是一个简单的拆分,但现在的问题是列“代码”现在在数据中包含空格(我只考虑了最后一列中的空格)。似乎是不变的(尽管我无法访问或控制源结构)是列之间至少有3个空格(可能更多,但从不少)。
所以,我想说我的列分隔符令牌是“3个空格”,然后修剪每个中的数据以获得我的实际柱状数据。
COL0 COL1 COL2 COL3 COL4 COL5
- 4 0.2 1 416489 463455 554
1 0.9 1 E1
0 3 1.4 14 E97-TEST 1
- 1 97.5 396 PASS Good
我只是想把这些值变成6个变量。
注意:COL0可能没有值。 COL4可能包含数据空间。 COL5可能不包含值,也不包含空格数据。所有固定格式都使用空格(没有制表符或其他特殊字符)。澄清一下 - 列的大小不一致。一个文件可能有COL4为13个字符,另一个文件有COL4,宽度为21个字符。或者不像另一个SO成员所说的那样严格。
答案 0 :(得分:3)
您需要确定列的位置。作为一个非常恶心的黑客,您可以读取整个文件,然后将字符串或行组合在一起:
my @file = <file>;
chomp @file;
my $t = "";
$t |= $_ foreach(@file);
然后$ t将在列中包含空格字符,只有该列中始终有空格字符;其他列将包含二进制垃圾。现在用一个匹配非空格的零宽度匹配来分割它:
my @cols = split /(?=[^ ]+)/, $t;
我们实际上希望列的 widths 生成unpack()格式:
@cols = map length, @cols;
my $format = join '', map "A$_", @cols;
现在处理文件! :
foreach my $line (@file) {
my($field, $field2, ...) = unpack $format, $line;
your code here...
}
(此代码仅经过轻微测试。)
答案 1 :(得分:2)
如果您正在处理严格的柱状数据,unpack
可能是您想要的:
#!perl
use strict;
use warnings;
use 5.010;
use Data::Dumper;
my $data = <<EOD;
COL0 COL1 COL2 COL3 COL4 COL5
- 4 0.2 1 416489 463455 554
1 0.9 1 E1
0 3 1.4 14 E97-TEST 1
- 1 97.5 396 PASS Good
EOD
my @lines = split '\n', $data;
for my $line ( @lines ) {
my @values = unpack("a5 A7 A7 A7 A13 A*", $line);
print Dumper \@values;
}
这似乎会根据您的意愿将您的值转储到@values
数组中,但它们会有前导空格,您必须将其剪掉。
答案 2 :(得分:1)
我会使用两个传递:在第一个中,找到每行中有空格的字符列;然后,用这些索引拆分或解包。之后进行空白修剪。
你的例子:
COL0 COL1 COL2 COL3 COL4 COL5
- 4 0.2 1 416489 463455 554
1 0.9 1 E1
0 3 1.4 14 E97-TEST 1
- 1 97.5 396 PASS Good
000011100001110000111000011100000000001110000000000
最后一行中的1
显示哪些列都是空格。
答案 3 :(得分:0)
我知道CanSpice已经回答了(可能是一个更好的解决方案),但您可以使用“$ /”设置输入分隔符。这必须在局部范围(可能是子范围)中完成,因为它是一个全局变量,或者您可能会看到副作用。例如:
local $/ = " ";
$input = <DATAIN>; # assuming DATAIN is the file-handler
您可以使用漂亮的小正则表达式修剪空白。有关示例,请参阅Wikipedia。