2015-12-14 3 views
0

Я новичок в unix. У меня есть вкладка DELIM текстового файл следующим образом:Извлечение подмножества записей для каждой записи на основе значения

ID  Region Strt End Length 
sd_2_1 head 241 930 689 
sd_2_1 trunk 16 240 224 
sd_2_1 tail 1 15 14 

sd_2_1 head 1 1 0 
sd_2_1 trunk 2 832 830 
sd_2_1 tail 833 930 97 

sd_2_1 head 780 930 150 
sd_2_1 trunk 663 779 116 
sd_2_1 tail 1  662 661 

sd_3_1 head 1020 1649 629 
sd_3_1 trunk 783 1019 236 
sd_3_1 tail 1  782 781 

sd_3_1 trunk 1  1470 1469 
sd_3_1 tail 1471 1649 178 

sd_4_1 head 2  50 48 
sd_4_1 trunk 51  701 650 

sd_4_1 head 1  40 38 
sd_4_1 trunk 41  101 60 
sd_4_1 tail 102 122 20 

Каждой Id множественное подмножество областей с различными элементами (разделенных пробелом), я хочу сравнить с каждыми ID со своим собственным подмножеством и сохранить только подмножество для каждого ID который имеет максимальную длину соединительной линии. В конце я хотел бы получить файл, как показано ниже:

 ID  Region Strt End Length 
    sd_2_1  head 1 1 0 
    sd_2_1  trunk 2 832 830 
    sd_2_1  tail 833 930 97 

    sd_3_1  trunk 1  1470 1469 
    sd_3_1  tail 1471 1649 178 

    sd_4_1  head 2  50 48 
    sd_4_1  trunk 51  701 650 

Любая помощь будет высоко оценена. Просьба направлять меня

+0

Почему в выходе нет строки '' '' '' sd_3_1'? и нет строки 'tail' для' sd_4_1'? – Kent

ответ

1

Вот Perl версии

while(<>) { 
    chomp; 
    if ($_ =~ /(head|trunk|tail)/) { 
     # Parse and store the relevant lines 
     ($id, $region, $start, $end, $length) = split; 
     $entry{$region} = $_; 
     if($region eq "trunk") { 
      $trunklength = $length; 
     } 
    } elsif(defined ($id)) { 
     # Check if this is the greatest trunk length 
     if($trunklength > $trunklength{$id}) { 
      # Clear old values 
      $trunklength{$id}= $trunklength; 
      undef($trunklength); 
      # Store new values 
      $trunk{$id} = $entry{"trunk"}; 
      $head{$id} = $entry{"head"}; 
      $tail{$id} = $entry{"tail"}; 
     } 
     undef %entry; 
    } 
} 
# Print out the answer 
foreach $id (sort (keys(%trunklength))) { 
    print "$head{$id}\n" if (defined($head{$id})); 
    print "$trunk{$id}\n" if (defined($trunk{$id})); 
    print "$tail{$id}\n" if (defined($tail{$id})); 
    print "\n"; 
} 

Она начинается с разбора головы, начало и хвост строки хранить их в хэш индексируется области. Длина канала сохраняется. На пустой строке длина соединительной линии сравнивается с сохраненной длиной соединительной линии для идентификатора. Если он больше, чем предыдущие значения для головы, туловища и длины отбрасываются и заменяются текущими версиями. Это относится к случаю, когда некоторые значения отсутствуют.

Наконец, проведите по хешам, чтобы распечатать требуемые значения. Обратите внимание, что perl делает очевидную вещь для неинициализированных переменных, поэтому нет необходимости проверять, чтобы $trunklength{id} не был установлен, например.

+0

Я изменил ответ, удалив ненужные 'undef' вызовы, например, $ head {$ id} = $ entry {" head "};' будет перезаписывать '$ head {$ id}} 'с неопределенным значением, если новая запись заголовка не установлена. –

0
  1. Для awk не существует входного файла. awk -F "\ t" '{if ($ 5 == max)}' ???

Это должно было AWK -F "\ т" '{если ($ 5 == макс)}' inFile.txt

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

  1. Что вы пытаетесь найти в grep? Вы не указали рисунок

  2. Ваш awk ничего не печатает. Я предполагаю, что это одноразовое требование и что вы уже знаете о максимальном значении.

    Ваша команда должна выглядеть

awk '{if($5==max1 || $5==max2 || $5==max3){ print $5 }}' infile.txt | sed 's/ /|/g' | xargs -ipattern grep -C 1 'pattern' >out.txt

-> Здесь я преобразования вывода мульти-линии от AWK, используя SED и использовали xargs передать шаблон для Grep
-> Здесь , если max1,2,3 не являются уникальными числами во всем файле, эта команда сломается.

+0

привет, Спасибо за ваш комментарий. На самом деле я хочу сохранить только один субет, который имеет максимальную длину ствола среди других и печатает его вместе с головой и хвостом. Для примера sd_2_1 имеет 3 подмножества с разной длиной соединительной линии, я бы хотел напечатать только суббет, который имеет максимальную длину соединительной линии. Пожалуйста, направляйте меня – Carol

+0

Да, Максимум 1,2 и 3, я имею в виду максимальные значения sd_2_1, sd_3_1 и sd_4_1 соответственно. Таким образом, он печатает самое высокое подмножество sd_2_1, sd_3_1, sd_4_1 – user3201336

3

awk на помощь!

$ (head -1 file && sed 1d file 
    | awk -v RS= '{len=0; 
        for(i=2;i<=NF;i+=5) 
         if($i=="trunk") {len=$(i+3); break} 
        if(len>v[$1]) {v[$1]=len; r[$1]=$0} 
        } 
       END{for(k in r) print r[k]}') 
    | column -t 

ID  Region Strt End Length 
sd_2_1 head 1  1  0 
sd_2_1 trunk 2  832 830 
sd_2_1 tail 833 930 97 
sd_3_1 trunk 1  1470 1469 
sd_3_1 tail 1471 1649 178 
sd_4_1 head 2  50 48 
sd_4_1 trunk 51 701 650 

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

Если вам нужно расстояние между разными строками ID.

... | column -t | awk 'NR<3{p=$1} $1!=p{print "";p=$1} 1' 

ID  Region Strt End Length 
sd_2_1 head 1  1  0 
sd_2_1 trunk 2  832 830 
sd_2_1 tail 833 930 97 

sd_3_1 trunk 1  1470 1469 
sd_3_1 tail 1471 1649 178 

sd_4_1 head 2  50 48 
sd_4_1 trunk 51 701 650 
Смежные вопросы