などの csv パーサーの使用Text::CSV
は複雑ではありません。このようなもので十分かもしれません:
use strict;
use warnings;
use Text::CSV;
my $csv = Text::CSV->new({
sep_char => "\t",
binary => 1,
eol => $/,
});
while (my $row = $csv->getline(*DATA)) {
tr/0/o/ for @{$row}[0, 1, 3]; # replace in cols A, B and D
s/(?<!\d)0(?!\d)/o/g for @{$row}[4]; # replace in col E
$csv->print(*STDOUT, $row); # print the result
}
__DATA__
A B C D E F
br0wn red 1278076 0range "20 tr0ut" 123
Green 0range 90876 Yell0w "18 Salm0n" 456
出力:
A B C D E F
brown red 1278076 orange "20 trout" 123
Green orange 90876 Yellow "18 Salmon" 456
混合文字列 (列 E) を音訳 (グローバル置換) ではなく単純な正規表現で処理したことに注意してください。数字の隣にあるゼロは単純に置き換えられませ20.0
ん0
。
アップデート:
位置ではなく列名に基づいて置換を行いたい場合、状況はもう少し複雑になります。しかし、Text::CSV
それを扱うことができます。
use strict;
use warnings;
use Text::CSV;
my @pure_text = qw(A B D);
my @mixed = qw(E);
my $csv = Text::CSV->new({
sep_char => "\t",
binary => 1,
eol => $/,
});
my $cols = $csv->getline(*DATA); # read column names
$csv->print(*STDOUT, $cols);
$csv->column_names($cols); # set column names
while (my $row = $csv->getline_hr(*DATA)) { # hash ref instead of array ref
tr/0/o/ for @{$row}{@pure_text}; # substitution on hash slice
s/(?<!\d)0(?!\d)/o/g for @{$row}{@mixed};
my @row = @{$row}{@$cols}; # make temp array for printing
$csv->print(*STDOUT, \@row);
}
__DATA__
A B C D E F
br0wn red 1278076 0range "20 tr0ut" 123
Green 0range 90876 Yell0w "18 Salm0n" 456
このコードは、デモ用のスタンドアロンです。ファイルでコードを試すには、スクリプトを次のように変更*DATA
して使用します。*STDIN
perl script.pl < input.csv