我有文本格式的数据文件有几行。现在有些行有错误的数据,我需要更新那些具有正确数据的行。例如,
Col1 Col2 Col3 Col4 .......
A1?% A foo fooo .......
B€(2 B .................
C&6 Z .................
A?04 Y .................
B++3 Q .................
C!5 C .................
D*9 D .................
实际数据不同,但这是它的简化版本。正如您所看到的,某些Col1中A1为A但A4为Y,依此类推。列Col3,Col4的其余列依赖于Col2。因此,当Col1中有A(A1,A2,A3等)时,我需要检查Col2是否为A.如果不是,我必须根据它所在的行更新Col2,Col3 ....
如何在Perl中实现这一目标。我知道这种操作可以在带有更新语句的数据库中完成,但我在这里没有那么奢侈,必须以编程方式进行。
编辑:文件以制表符分隔,数据是可包含任何字母数字或ascii字符的字符串。
答案 0 :(得分:2)
我这样做的方法是打开一个输入文件句柄和一个输出文件句柄,然后逐行浏览文件检查第一列,如果它很好,只需将它放入我的输出就好了。
如果确实需要更改,我会使用必要的更改创建一个新行,并将其放入我的输出文件中。
这是一种简单的方法,虽然不是最伟大/优雅/无论什么,但它可以快速为您提供所需。
答案 1 :(得分:1)
填充键,其中键为Col2(A,B,C等),其值为其余列(Col3,Col4等)。如果Col1和Col2匹配,只能将Col2作为密钥。
然后在写出文件时,如果Col1和Col2不匹配,请在Col1的第一个字符的哈希中进行查找。这将为您提供要插入的Col3,Col4 ...值。
答案 2 :(得分:1)
使用CSV处理器!
至少Text::CSV
或亲属,如Text::CSV_XS
(更快)或Text::CSV::Encoded
(例如,对于UTF-8)。
DBD::CSV
提供SQL。
答案 3 :(得分:0)
以下是允许您执行此操作的基本程序结构的框架。如果我知道你想做什么,我会更有帮助。
我做出了最简单的猜测,并且我将输入文件视为宽度= 7,6,*的固定列。正如您已经告诉我它们是制表符分隔的,我已经更改了将数据分解为字段的代码。
use autodie;
use strict;
use warnings;
use English qw<$INPUT_LINE_NUMBER>;
my %data;
my $line_no;
open ( my $h, '<', 'good_file.dat' );
while ( <$h> ) {
my ( $col1, $col2, $data ) = split( /\t+/, $_, 3 );
# next unless index( $col1, 'A' ) == 0;
$line_no = $INPUT_LINE_NUMBER;
my $rec
= { col1 => $col1
, col2 => $col2
, data => $data
, line => $line_no
};
push( @{ $data{"$col1-$col2"} }, $rec );
$data{ $line_no } = $rec;
}
close $h;
open ( $h, '<', 'old_file.dat' );
while ( <$h> ) {
my ( $col1, $col2, $data ) = split( /\t+/, $_, 3 );
...
}
以下是您可以将值打印回文件的方法。
open ( $h, '>', 'old_file.dat' );
foreach my $rec ( grep {; defined } @data{ 1..$line_no } ) {
printf $h "%s\t%s\t%s\n", @$rec{qw<col1 col2 data>};
}
但你真的没有给予任何足够的帮助来帮助你。