如何使用 perl 计算 UCSC 摆动文件的倒数 log2 比率?

How to calculate inverse log2 ratio of a UCSC wiggle file using perl?

我有 2 个单独的文件,即 A 和 B,包含相同的 header 行,但分别包含 2 列和 1 列。我想在单独的文件中采用第二列或第一列的倒数 log2,但保持其他描述不变。我遇到了这样的事情。文件 A $1 和 $2 中的值由定界符 tab
分隔 文件A

track type=wiggle_0 name=rep1.bar.wig description=GSM1076_rep1.bar.wig graphType=bar  
variableStep chrom=chr1  
12  0.781985  
16  0.810993  
20  0.769601  
24  0.733831  

文件B

track type=wiggle_0 name=rep1.bar.wig description=GSM1078_rep1.bar.wig graphType=bar
variableStep chrom=chr1  
0.721985  
0.610993  
0.760123  
0.573831  

我期待这样的输出。 文件A

track type=wiggle_0 name=rep1.bar.wig description=GSM1076_rep1.bar.wig graphType=bar  
variableStep chrom=chr1  
12  1.7194950944  
16  1.754418585  
20  1.7047982296  
24  1.6630493726  
track type=wiggle_0 name=rep1.bar.wig description=GSM1076_rep1.bar.wig  graphType=bar  
variableStep chrom=chr2 

对于文件 B(在此文件中,值只是文件 A 的复制粘贴)

track type=wiggle_0 name=rep1.bar.wig description=GSM1078_rep1.bar.wig  graphType=bar  
variableStep chrom=chr1   
1.7194950944  
1.754418585  
1.7047982296  
1.6630493726  
track type=wiggle_0 name=rep1.bar.wig description=GSM1078_rep1.bar.wig rep1.bar.wig graphType=bar  
variableStep chrom=chr2

这个 awk 脚本执行您想要的计算:

awk '/^[0-9.[:space:]]+$/{$NF=sprintf("%.12f", 2^$NF)}1' file

这匹配仅包含数字、句点和任何 space 个字符的行,将最后一个字段的值 $NF 替换为 2 的 $NF 次方。可以修改格式说明符 %.12f 以提供所需的小数位数。最后的 1 是 shorthand for {print}.

正在您的新文件上进行测试:

$ awk '/^[0-9.[:space:]]+$/{$NF=sprintf("%.12f", 2^$NF)}1' A   
track type=wiggle_0 name=rep1.bar.wig description=GSM1076_rep1.bar.wig graphType=bar  
variableStep chrom=chr1  
12 1.719495094445
16 1.754418584953
20 1.704798229573
24 1.663049372620
$ awk '/^[0-9.[:space:]]+$/{$NF=sprintf("%.12f", 2^$NF)}1' B
track type=wiggle_0 name=rep1.bar.wig description=GSM1078_rep1.bar.wig graphType=bar
variableStep chrom=chr1  
1.649449947457
1.527310087388
1.693635012985
1.488470882686

这是 Perl 版本:

use strict;
open IN, $ARGV[0];
while (<IN>) {
  chomp;  
  if (/^(.*)[\t ]*(-?\d\.\d*)/) { # format "nn m.mmmmm"
    my $power = 2 ** ;
    print("\t" . $power . "\n");
  } elsif (/^(-?\d\.\d*)/) { # format "m.mmmmm"
    my $power = 2 ** ;
    print($power . "\n");
  } else { # echo all other stuff
    print;
    print ("\n");
  }
}
close IN;

如果您 运行 <file>.pl <datafile>(替换为适当的名称),它将转换一个文件,因此行具有 2**<第二个值>)。它只是回显与数字模式不匹配的行。

This is the modified little script of @ThomasKilian
Thanks to him for providing the framework.

use strict;
    open IN, $ARGV[0];
    while (<IN>) {
      chomp;  
      if (/^(\d*)[\t ]*(-?\d\.\d*)/) { # format "nn m.mmmmm"
        my $power = 2 ** ;
        $power= sprintf("%.12f", $power);
        print("\t" . $power . "\n");
      } elsif (/^(-?\d\.\d*)/) { # format "m.mmmmm"
        my $power = 2 ** ;
        $power= sprintf("%.12f", $power);
        print($power . "\n");
      } else { # echo all other stuff
        print;
        print ("\n");
      }
    }
    close IN;