У меня есть два файла, оба они разделены каналом.
Первый файл: может быть около 10 столбцов, но меня интересуют первые два столбца, которые будут полезны при обновлении значения столбца второго файла.
детали первого файла:
1|alpha|s3.3|4|6|7|8|9
2|beta|s3.3|4|6|7|8|9
20|charlie|s3.3|4|6|7|8|9
6|romeo|s3.3|4|6|7|8|9
Вторая информация о файле:
a1|a2|**bob**|a3|a4|a5|a6|a7|a8|**1**|a10|a11|a12
a1|a2|**ray**|a3|a4|a5|a6|a7|a8||a10|a11|a12
a1|a2|**kate**|a3|a4|a5|a6|a7|a8|**20**|a10|a11|a12
a1|a2|**bob**|a3|a4|a5|a6|a7|a8|**6**|a10|a11|a12
a1|a2|**bob**|a3|a4|a5|a6|a7|a8|**45**|a10|a11|a12
Мое требование здесь - найти уникальные значения из 3-го столбца, а также заменить 4-й столбец из последнего. 4-й столбец от последнего может иметь/не иметь числового номера. Этот номер также появится в первом поле первого файла. Мне нужно заменить (второй файл) это число соответствующим значением, которое появляется во втором столбце первого файла.
ожидаемый результат:
уникальная строка: Рэй Кейт Боб
a1|a2|bob|a3|a4|a5|a6|a7|a8|**alpha**|a10|a11|a12
a1|a2|ray|a3|a4|a5|a6|a7|a8||a10|a11|a12
a1|a2|kate|a3|a4|a5|a6|a7|a8|**charlie**|a10|a11|a12
a1|a2|bob|a3|a4|a5|a6|a7|a8|**romeo**|a10|a11|a12
a1|a2|bob|a3|a4|a5|a6|a7|a8|45|a10|a11|a12
Я могу выбрать уникальную строку, используя команду ниже
awk -F'|' '{a[$3]++}END{for(i in a){print i}}' filename
Я бы не хотел читать второй файл дважды, сначала выбрать уникальную строку, а второй раз заменить 4-й столбец из последнего, так как размер файла огромен. Это будет около 500 МБ, и таких файлов много.
В настоящее время я использую модуль perl (Text::CSV)
для чтения первого файла (этот файл имеет небольшой размер) и загрузки первых двух столбцов в хеш, рассматривая первый столбец как ключ, а второй как значение. затем прочитайте второй файл и замените столбец n-4 хэш-значением. Но это кажется трудоемким, так как парсинг Text::CSV кажется медленным.
Любое решение awk/perl с учетом скорости было бы очень полезно :)
Примечание. Не обращайте внимания на звездочки ** вокруг текста, они просто подчеркивают, что они не являются частью данных.
ОБНОВЛЕНИЕ: код
#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Utils;
use Text::CSV;
my %hash;
my $csv = Text::CSV->new({ sep_char => '|' });
my $file = $ARGV[0] or die "Need to get CSV file on the command line\n";
open(my $data, '<', $file) or die "Could not open '$file' $!\n";
while (my $line = <$data>) {
chomp $line;
if ($csv->parse($line)) {
my @fields = $csv->fields();
$hash{$field[0]}=$field[1];
} else {
warn "Line could not be parsed: $line\n";
}
}
close($data);
my $csv = Text::CSV->new({ sep_char => '|' , blank_is_undef => 1 , eol => "\n"});
my $file2 = $ARGV[1] or die "Need to get CSV file on the command line\n";
open ( my $fh,'>','/tmp/outputfile') or die "Could not open file $!\n";
open(my $data2, '<', $file2) or die "Could not open '$file' $!\n";
while (my $line = <$data2>) {
chomp $line;
if ($csv->parse($line)) {
my @fields = $csv->fields();
if (defined ($field[-4]) && looks_like_number($field[-4]))
{
$field[-4]=$hash{$field[-4]};
}
$csv->print($fh,\@fields);
} else {
warn "Line could not be parsed: $line\n";
}
}
close($data2);
close($fh);
use Text::CSV;
будет автоматически использовать версию XS. - person ThisSuitIsBlackNot   schedule 31.03.2014Text::CSV
- person chidori   schedule 31.03.2014Text::CSV
используетсяgetline
, а неparse
:while (my $row = $csv->getline($fh)) { ... }
. В этом случае$row
является ссылкой на массив, поэтому вы можете получить доступ к первому полю с помощью$row->[0]
и получить все поля с помощью@$row
. Я не тестировал его, поэтому не уверен, будет ли это иметь существенное значение для скорости или нет. - person ThisSuitIsBlackNot   schedule 31.03.2014auto_diag
для методаnew
, ошибка будет отображаться автоматически, если строка не может быть проанализирована с помощьюgetline
, поэтому вам не нужно добавлять кучу операторовor die ...
:my $csv = Text::CSV->new({ sep_char => '|', auto_diag => 1 });
- person ThisSuitIsBlackNot   schedule 31.03.2014$csv
? С разными вариантами. - person TLP   schedule 31.03.2014getline
значительно быстрее, чемparse
. - person ThisSuitIsBlackNot   schedule 31.03.2014