Perl-скрипт для обновления одной строки файла другой

У меня есть файлы данных в текстовом формате, в которых есть несколько строк. Теперь есть определенные строки с неправильными данными, которые мне нужно обновить с помощью тех, которые имеют правильные данные. Например,

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. Итак, мне нужно проверить, является ли Col2 A, когда в Col1 есть A (A1, A2, A3 и т. Д.). Если нет, мне нужно обновить Col2, Col3 .... на основе строки, где это A.

Как это можно сделать в Perl. Я знаю, что такие операции можно выполнять в базе данных с помощью оператора обновления, но у меня нет такой роскоши, и мне приходится делать это программно.

Изменить: файлы разделены табуляцией, а данные представляют собой строки, которые могут содержать любые буквенно-цифровые символы или символы ascii.


person sfactor    schedule 07.02.2011    source источник
comment
Пожалуйста, поясните: хранятся ли данные в файле, разделенном пробелами? Могут ли ячейки содержать только буквенно-цифровые символы? Имеет ли A1 более высокий приоритет, чем A4, потому что его номер ниже или потому что его строка выше?   -  person Tim    schedule 07.02.2011
comment
Я думаю, вы думаете, что вы несколько ясны, но вы говорите, что можете сделать это в базе данных, возможно, если вы разместите аналогичный SQL, мы сможем лучше понять: 1) что вы пытались обновить, 2) с чем, 3) в каких условиях.   -  person Axeman    schedule 07.02.2011
comment
@Tim Я добавил информацию, которую, кажется, забыл добавить. Ячейки могут содержать любой символ, и A1 имеет более высокий приоритет, потому что я знаю, что Col2 - это A в этом случае, поэтому это немного ручного поиска.   -  person sfactor    schedule 08.02.2011
comment
Что произойдет, если данные содержат символ TAB?   -  person reinierpost    schedule 08.02.2011
comment
Итак, B должен быть B или Q? C должен быть Z или C. Вы говорите «ручной поиск» - как вы предлагаете программный поиск вручную?   -  person Dennis Williamson    schedule 08.02.2011


Ответы (4)


Я бы сделал это так, чтобы открыть дескриптор входного файла и дескриптор выходного файла и пройти построчно через первый столбец проверки файла и, если все в порядке, просто вставить его в свой вывод, как есть.

Если это действительно нужно изменить, я бы сделал новую строку с необходимыми изменениями и тоже поместил бы ее в свой выходной файл.

Это простой подход, который, хотя и не самый лучший / элегантный / что угодно, быстро даст вам то, что вам нужно.

person Weegee    schedule 07.02.2011
comment
Вам понадобится какой-то способ сохранить правильные значения, которые вы хотите вставить, когда вы просматриваете файл, и вы, возможно, не видели все правильные значения. - person Girish Rao; 07.02.2011
comment
@ Гириш Сорта. Похоже, что данный col2 - это X, col3 и col4 одинаковы. Таким образом, X1, X2 и X3 будут иметь одинаковые col3 и col4. Все, что ему нужно, это посмотреть на col1, после чего он сможет выбрать правильную информацию из хеш-структуры данных для col2, col3 и col4. - person Weegee; 07.02.2011

Заполните хэш-карту, где ключ - это Col2 (A, B, C и т. Д.), А значение - это остальные столбцы (Col3, Col4 и т. Д.). Сделайте Col2 ключом, только если Col1 и Col2 совпадают, как вы хотите.

Затем при записи файла, если Col1 и Col2 не совпадают, выполните поиск в хэше по первому символу Col1. Это даст вам значения Col3, Col4 ... для вставки.

person Girish Rao    schedule 07.02.2011

Используйте процессор CSV!

По крайней мере, Text::CSV или родственники, такие как Text::CSV_XS (быстрее) или Text::CSV::Encoded (например, для UTF-8).

DBD::CSV предоставляет SQL.

person reinierpost    schedule 08.02.2011
comment
+1 за использование модуля CSV, хотя это решает только часть вопроса. - person Tim; 08.02.2011

Ниже приведен скелет базовой структуры программы, которая позволяет вам это делать. Если бы я знал, что вы хотите сделать, я был бы намного полезнее.

Я сделал самое простое возможное предположение и обработал ваши входные файлы, как если бы они были фиксированными столбцами с шириной = 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>};
}

Но вы действительно никому не оказали достаточно помощи, чтобы помочь вам.

person Axeman    schedule 07.02.2011
comment
Я должен был быть более ясным и добавить дополнительную информацию, которая может сделать ее более ясной. Столбцы могут иметь любые символы, поэтому, например, когда я говорю, что ищу A в A1, A2, A3, это больше похоже на поиск этой подстроки в более длинной строке для совпадения с целью обновления. - person sfactor; 08.02.2011
comment
@sfactor, Хорошо, я могу изменить код, чтобы лучше фиксировать эти данные, но вы до сих пор не дали четкого указания на условия и модификации. - person Axeman; 08.02.2011
comment
На самом деле я создал еще один вопрос, надеясь, что он будет более ясным. Тем не менее, это кажется неясным. Но я думаю, это прояснит вопрос. stackoverflow.com/questions/4931783/ - person sfactor; 08.02.2011