Умножение значений из столбца в соответствии с определенным регулярным выражением с использованием Perl - PullRequest
0 голосов
/ 29 января 2012

У меня есть большой файл с разделителями табуляции (10 ГБ) с 8 столбцами.

Col1        Col2    Col3 Col4     Col5        Col6       Col7    Col8

101_#2        1       2    F0       263        248        2       1.5

102_#1        1       6    F1       766        741        1       1.0

103_#1        2       15   V1       526        501        1       0.0

103_#1        2       9    V2       103        178        1       1.3

104_#1        1       12   V3       137        112        1       1.0

105_#1        1       17   F2       766        741        1       1.0

Я хочу умножить значения в col8 на значения в col1, присутствующие после "#" (в col1), чтобы вывестидолжно быть ->

Col1        Col2    Col3 Col4     Col5        Col6       Col7    Col8

101_#3        1       2    F0       263        248        2       1.5

102_#1        1       6    F1       766        741        1       1.0

103_#0        2       15   V1       526        501        1       0.0

103_#1.3      2       9    V2       103        178        1       1.3

104_#1        1       12   V3       137        112        1       1.0

105_#1        1       17   F2       766        741        1       1.0

Первая строка - заголовок, и я хочу, чтобы то же самое в выводе (поэтому никаких изменений для 1-й строки).

Усилие:

use strict;
use warnings;

@ARGV or die "No input file specified";

open my $fh, '<', $ARGV[0] or die "Unable to open input file: $!";
print scalar(<$fh>);

while (<$fh>) {
    chomp;
}

Ответы [ 4 ]

2 голосов
/ 29 января 2012

При отсутствии согласованных усилий со стороны ФП, объяснения должно быть достаточно:

  • Использовать однострочник Perl для построчной обработки этого файла
  • Флаг -i включит редактирование файла на месте. -i.bak создает резервную копию
  • Используйте $. в условном выражении, чтобы пропустить строку заголовка
  • Доступ к столбцам 1 и 8 можно получить с помощью флага -a, который автоматически разбивает строку на пробелах для создания массива @F. Флаг -F может использоваться для указания разделителя. Тестирование на @F пустоту также можно использовать для пропуска пустых строк
  • Конструкция s///e будет полезна для обновления значения до того, что вы хотите
  • с автоматическим добавлением флага -l

См. perldoc perlrun, perldoc perlretut и perldoc perlop для получения дополнительной информации

1 голос
/ 29 января 2012

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

use strict;
use warnings;

# Skip header rows
print scalar(<>);
print scalar(<>);

# Process each other line
while (<>) {
    # Skip empty lines
    print and next if /^\s*$/;
    # Split on whitespace
    my @cols = split(/\s+/);
    # Split the first column on '#', removing it from the column list
    my ($p1, $p2) = split(/#/, shift @cols);
    # Multiply and print (original whitespace replaces with tabs
    print $p1, "#", $cols[6]*$p2, "\t", join("\t", @cols), "\n";
}
0 голосов
/ 29 января 2012

Если ваши данные соответствуют CSV-данным, я бы предложил использовать модуль CSV при его анализе. Например, Text :: CSV или Text :: CSV_XS .

Замените дескрипторы файлов DATA и STDOUT при необходимости. Параметры CSV, возможно, должны быть настроены в соответствии с вашими данными, обратитесь к документации. Это базовое использование модуля Text :: CSV_XS :

#!/usr/bin/perl
use strict;
use warnings;

use Text::CSV_XS;

my $csv = Text::CSV_XS->new({
        sep_char => "\t",
        binary  => 1,
        eol     => $/,
    });

my $hrs = <DATA>;
print $hrs;

while (my $row = $csv->getline(*DATA)) {
    $row->[0] =~ s/#\K(\d+)$/ $row->[7] * $1 /e;
    $csv->print(*STDOUT, $row );
}

__DATA__
Col1    Col2    Col3    Col4    Col5    Col6    Col7    Col8
101_#2  1   2   F0  263 248 2   1.5
102_#1  1   6   F1  766 741 1   1.0
103_#1  2   15  V1  526 501 1   0.0
103_#1  2   9   V2  103 178 1   1.3
104_#1  1   12  V3  137 112 1   3.0
105_#1  1   17  F2  766 741 1   23.0

Обратите внимание, что приведенные выше данные могут не содержать надлежащих вкладок из-за преобразования StackOverflow.

0 голосов
/ 29 января 2012

Использование unpack:

use strict;
use warnings;
no warnings 'uninitialized';

# fixed-width file, so use unpack
# offsets: 20 28 33 42 58 74 82

my $header = <>; # ignore

while ( <> ) {
#   print;
    my @cols = unpack 'a19 a8 a5 a9 a16 a16 a8 a*';
#   print "$_\n" for @cols; exit;
    s/\s+$// for @cols; # trim
#   print join(', ', @cols), "\n";
    my $num;
    if ( 0 <= (my $idx = rindex $cols[0], '#') ) {
        $num = substr $cols[0], $idx + 1;
    }
    else {
        warn "no number after # in col1\n";
    }
    printf "%f * %f = %f\n", $num, $cols[7], $num * $cols[7];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...