2014-02-21 4 views
1

Я хочу заменить цифры «0» из второго столбца на второй столбец другого файла. Например, вход 1, chr1, второй столбец «0», и я хотел бы заменить это на «754192» из второго столбца из файла ввода 2, и я хотел бы сделать это с другими цифрами «0» из так что для chr2 во входе 1 во втором столбце вместо «0» он будет читать «83616» из файла ввода 2. Оба входных файла разделены на вкладку. Я бы очень признателен за любые предложения perl/awk. Спасибо.соответствуют и заменяют разные значения в том же столбце из списка

вход 1

chr1 0  121347754  0.004130250308662653 
chr1 144009053  249250621  0.12551644444465637 
chr2 0  90278124  -0.010306187905371189 
chr2 95387134  243199373  -0.011985263787209988 
chr3 0  91000000  -0.009726814925670624 
chr3 93541117  198022430  -0.014836171641945839 
chr4 0  49064792  -0.01315629668533802 
chr4 52700771  141568601  0.014452865347266197 
chr4 141568601  143871023  0.20834201574325562 
chr5 0  46113638  -0.013212060555815697 
chr5 49560859  68740653  0.004888067487627268 
chr5 70744658  180915260  -0.011330894194543362 

вход 2

chr1 754192 
chr2 83616 
chr3 108226 
chr4 90883 
chr5 40975 
chr6 209980 
chr7 67820 
chr8 193585 
chr9 206255 
chr10 126070 

Выходной

chr1 754192  121347754  0.004130250308662653 
chr1 144009053  249250621  0.12551644444465637 
chr2 83616  90278124  -0.010306187905371189 
chr2 95387134  243199373  -0.011985263787209988 
chr3 108226  91000000  -0.009726814925670624 
chr3 93541117  198022430  -0.014836171641945839 
chr4 90883  49064792  -0.01315629668533802 
chr4 52700771  141568601  0.014452865347266197 
chr4 141568601  143871023  0.20834201574325562 
chr5 40975  46113638  -0.013212060555815697 
chr5 49560859  68740653  0.004888067487627268 
chr5 70744658  180915260  -0.011330894194543362 
+0

Tab разделенных данных? – Kenosis

+0

да вкладки разделенные данные – user3324491

+1

Вы, кажется, сделали это просто отлично! Пожалуйста, покажите, что вы пробовали и нуждаетесь в помощи, а не просите бесплатный код. – Borodin

ответ

2

Вы можете попробовать это awk,

awk 'NR==FNR{ a[$1]=$2; next;} $2==0{ $2=a[$1]; }1' OFS="\t" input2 input1 
+1

+1. вам не нужно использовать 'if' хотя:' $ 2 == 0 {$ 2 = a [$ 1]} 1' –

+0

@glennjackman, спасибо. Обновлен ответ. – sat

2
perl -MFile::Slurp -lape' 
    BEGIN { %h = map split, read_file(pop); } 
    $F[1] ||= $h{$F[0]}; 
    $_ = join "\t", @F; 
' input1 input2 

выход

chr1 754192  121347754  0.004130250308662653 
chr1 144009053  249250621  0.12551644444465637 
chr2 83616  90278124  -0.010306187905371189 
chr2 95387134  243199373  -0.011985263787209988 
chr3 108226  91000000  -0.009726814925670624 
chr3 93541117  198022430  -0.014836171641945839 
chr4 90883  49064792  -0.01315629668533802 
chr4 52700771  141568601  0.014452865347266197 
chr4 141568601  143871023  0.20834201574325562 
chr5 40975  46113638  -0.013212060555815697 
chr5 49560859  68740653  0.004888067487627268 
chr5 70744658  180915260  -0.011330894194543362 
+0

Вы имели в виду 'input2 input1', используя метки OP? – Kenosis

+0

Зачем врезаться, когда вам не нужно? – TLP

+0

@ Kenosis input2 считывается в% h –

1

Чуть более процедурную версию (без проверки ошибок).

use Modern::Perl; 
use autodie; 

# read input2 into map 
my %input2 = do { 
    open my $input2, '<', "input2"; 
    local $/ = undef; 
    split(' ', <$input2>); 
}; 

open my $input1, '<', "input1"; 
while (<$input1>) { 
    my ($id) = split(' '); 
    if (/^\w+\s+0\s/) { 
    my $replace_with = $input2{$id}; 
    s/^(\w+\s+)0(\s)/$1$replace_with$2/; 
    } 

    print; 
} 
+2

Зачем клонировать файл, когда вам не нужно? Вы рискуете получить одноразовые ошибки, если какое-то значение отсутствует, и ничего не получите. Кроме того, используйте '' '' вместо '/ \ s + /', если вы не хотите сохранять ведущие пробелы. Кроме того, '\ b0 \ b' соответствует' 0.123' - вам нужно использовать 'eq' или' == '. – TLP

+0

привет, не могли бы вы объяснить, почему мне не нужно разрывать файл? (input2 имеет символы новой строки). Также не уверен, что вы имеете в виду с == или eq. спасибо за отзывы. – Richard

+1

Вы можете читать строки за строкой и разбивать каждую строку, используя, например, 'map'. На самом деле, вы рискуете разовыми ошибками, так как 'split' будет разделять пробельные пробелы, если вы специально не назначили пару значений ключа, т. Е.' Map {my ($ k, $ v) = split; $ k => $ v; } <$input2> '. Использование 'eq' обеспечит равенство строк,' == 'числовое равенство, и вы примените их к значению, которое вы получаете от разделения строки. – TLP

2

Это один из способов сделать это на Perl. Программа ожидает пути к двум файлам в качестве параметров в командной строке.

use strict; 
use warnings; 

my ($file1, $file2) = @ARGV; 
my $fh; 

open $fh, '<', $file2 or die qq{Unable to open "$file2" for input: $!}; 
my %defaults = map {(split)[0,1]} <$fh>; 

open $fh, '<', $file1 or die qq{Unable to open "$file1" for input: $!}; 

while (<$fh>) { 
    my @fields = split; 
    $fields[1] ||= $defaults{$fields[0]}; 
    print join("\t", @fields), "\n"; 
} 

выход

chr1 754192 121347754 0.004130250308662653 
chr1 144009053 249250621 0.12551644444465637 
chr2 83616 90278124 -0.010306187905371189 
chr2 95387134 243199373 -0.011985263787209988 
chr3 108226 91000000 -0.009726814925670624 
chr3 93541117 198022430 -0.014836171641945839 
chr4 90883 49064792 -0.01315629668533802 
chr4 52700771 141568601 0.014452865347266197 
chr4 141568601 143871023 0.20834201574325562 
chr5 40975 46113638 -0.013212060555815697 
chr5 49560859 68740653 0.004888067487627268 
chr5 70744658 180915260 -0.011330894194543362 
+0

Ваш выход не соответствует ожидаемому выходу OP. Сравните, например, первую строку 'chr5'. – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot: Спасибо. Я исправил это. – Borodin

1

Один вкладыш в Perl:

$ perl -MFile::Slurp -lape 'BEGIN {$" = "\t"; %input = map { m/([^\s]+)\s*([^\s]+)/ } read_file("input_2")} $F[1] = $input{$F[0]} unless $F[1]' input_1 
+4

'[^ \ s]' лучше написано '\ S' – TLP

+1

Исправлено это для вас. Кроме того, с должным уважением, разве вы не думаете, что ваш ответ - это своего рода отрыв от уже полученных ответов? – TLP

+0

Я еще больше укоротил его, чтобы не отставать от духа Perl. Ваше должное уважение хорошо воспринято, когда я открыл вопрос, были нулевые ответы ... Я не проверял/не обновлял страницу, прежде чем отправил свой окончательный ответ, который я тестировал, прежде чем он работал. – lzc

 Смежные вопросы

  • Нет связанных вопросов^_^