Сортировать файл по столбцу

#arrays #perl #sorting

#массивы #perl #сортировка

Вопрос:

Я пытаюсь отсортировать файл, который выглядит следующим образом

 MarkerName      Allele1 Allele2 Weight  Zscore  P-value Direction^Mrs217377     t       c       6806    1.121   0.2625     ^Mrs4668077
  a       g       6806    -0.038  0.9696  -- ^Mrs16855496 a       g       4106    -0.092  0.9268  ??-^Mrs217386   a       g       6806
    0.814   0.4158     ^Mrs2075070  a       g       6806    -0.699  0.4844  -- ^Mrs10187002 a       t       4106    0.099   0.9208  ?? ^Mrs12785983 t       c       6806    -1.092  0.2747   --^Mrs1100405  t       c       6806    -0.872  0.3831   --^Mrs12155014 t       c
       6806    0.081   0.9358    -^Mrs2287619  t       c       6806    -2.221  0.02632 ---^M
  

После седьмого пробела вместо простого перевода строки стоит ^M символ. Я не совсем уверен, как с этим бороться или я могу просто проигнорировать это.
Я пытаюсь отсортировать каждую строку по P-значению (шестому) столбцу.

Вот так:

 MarkerName      Allele1 Allele2 Weight  Zscore  P-value Direction
rs2287619       t       c       6806    -2.221  0.02632 ---
rs217377        t       c       6806    1.121   0.2625     
rs12785983      t       c       6806    -1.092  0.2747   --
rs1100405       t       c       6806    -0.872  0.3831   --
rs217386        a       g       6806    0.814   0.4158     
rs2075070       a       g       6806    -0.699  0.4844  -- 
rs10187002      a       t       4106    0.099   0.9208  ?? 
rs16855496      a       g       4106    -0.092  0.9268  ??-
rs4668077       a       g       6806    -0.038  0.9696  -- 
  

Пока у меня есть этот Perl-код

 use strict; 
use warnings;

die "Please specify a suitable text filen" if (@ARGV != 1);
my ($infile) = @ARGV;

# create outputfile
my $outfile = "MetaAnalysis_Sorted.txt";

# create filehandles
open (my $in, " < $infile") or die "error reading $infile. $!";
open (my $out, " >> $outfile") or die "error creating $outfile. $!";


my @array;

while ( <$in> ) {
    chomp;  # removes newline
    push @array, $_;
    my @sorted = sort { (split 's', $a)[5] <=> (split 's', $b)[5] } @array;
    print $out join( "n", @sorted )."nn";
}

close $in;
close $out; 
  

Я пытался преобразовать исходный файл с помощью dos2unix , но это не сработало.

Комментарии:

1. Символ возврата каретки (0x0d) отображается как ^M в Vim, если fileformat=unix . Просматриваете ли вы файл в Vim?

2. Я просматриваю файл в Unix с помощью команды less, которая обычно отделяет возвраты каретки нормально, я не должен беспокоиться о сортировке, если я просматриваю в текстовом редакторе после?

3. perl -pe 's/[rn] /n/' yourfile

4. Это помогло бы, но я никогда не рекомендую это кому-либо с командой example, потому что вмешиваться в чьи-либо исходные данные неприятно.

Ответ №1:

Основная проблема заключается в том, что вы используете 's' литерал вместо регулярного выражения. Вероятно, вы имели в виду один или несколько пробелов, т.е. /s / .

Другая проблема связана с nun-числовым, P-value переданным <=> оператору. Я предлагаю перед вызовом убрать заголовок из массива sort .

Запись выходного файла должна выполняться вне while (<$in>) цикла.

Кроме того, я предлагаю пропускать пустые строки:

 while (<$in>) {
    chomp;  #removes new line
    push @array, $_ if $_;
}
  

Вот исправленная версия:

 use strict; use warnings;

die "Please specify a suitable text filen" if (@ARGV != 1);
my ($infile) = @ARGV;

#create outputfile
my $outfile = "MetaAnalysis_Sorted.txt";

#create filehandles
open (my $in, " < $infile") or die "error reading $infile. $!";
open (my $out, " >> $outfile") or die "error creating $outfile. $!";


my @array;
while (<$in>) {
    chomp;  #removes new line
    push @array, $_ if $_;
}


my $head = shift @array;
print $out "$headn";

my @sorted = sort {
  (split /s /, $a)[5] <=> (split /s /, $b)[5];
} @array;
print $out join( "n", @sorted )."nn";

close $in;
close $out;
  

Ответ №2:

Последовательность ^M используется многими редакторами и текстовыми утилитами для обозначения Ctrl-M или возврата каретки. Похоже, что ваш файл был сохранен только с возвратом каретки (CR) в конце каждой строки. Это очень необычно. Linux использует только перевод строки (LF), в то время как Windows использует два символа CR LF. Только в гораздо более старых системах Macintosh использовался только CR

Последовательность символов регулярного выражения R может быть очень полезна для файлов такого типа. Он будет соответствовать любому из LF, CR LF или просто CR. К сожалению, вы не можете установить разделитель строк ввода в соответствии с шаблоном регулярных выражений — это должна быть буквальная строка, поэтому вам придется прочитать весь файл в одну строку, а затем использовать split

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

sort_by_col6.pl

 use strict;
use warnings 'all';

my @infile = do {
    local $/;
    split /R/, <>;
};

local $ = "n";

print shift @infile;    # Print header line
print for sort { (split ' ', $a)[5] <=> (split ' ', $b) } @infile;
  

Вам нужно будет запустить его из командной строки следующим образом, чтобы перенаправить вывод

 $ perl sort_by_col6.pl my_input.txt > MetaAnalysis_Sorted.txt