2016-01-07 3 views
0

Say У меня file.txtВывести номер строки, когда есть совпадающее значение для каждого столбца

Position name1 name2 name3 
     2  A  G  F 
     4  G  S  D 
     5  L  K  P 
     7  G  A  A 
     8  O  L  K 
     9  E  A  G 

и мне нужно, чтобы получить выход:

name1 name2 name3 
    2  2  7 
    4  7  9 
    7  9 

Он выводит каждое имя и номера позиций, где есть A или G

В файле file.txt столбец name1 имеет A в позиции 2, G в позициях 4 и 7 ... поэтому в выходном файле: 2, 4,7 указана под именем1 ... и т. Д.

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

Я уверен, что есть лучший способ использовать awk или bash ... идеи оценены.

+0

Если вы удалите тег 'r', удалите' Тогда я получаю результат для каждого столбца и свяжу их вместе, используя r? '. –

+0

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

+1

Лучше показать ** попытки ** –

ответ

3
$ cat tst.awk 
NR==1 { 
    for (nameNr=2;nameNr<=NF;nameNr++) { 
     printf "%5s%s", $nameNr, (nameNr<NF?OFS:ORS) 
    } 
    next 
} 
{ 
    for (nameNr=2;nameNr<=NF;nameNr++) { 
     if ($nameNr ~ /^[AG]$/) { 
      hits[nameNr,++numHits[nameNr]] = $1 
      maxHits = (numHits[nameNr] > maxHits ? numHits[nameNr] : maxHits) 
     } 
    } 
} 
END { 
    for (hitNr=1; hitNr<=maxHits; hitNr++) { 
     for (nameNr=2;nameNr<=NF;nameNr++) { 
      printf "%5s%s", hits[nameNr,hitNr], (nameNr<NF?OFS:ORS) 
     } 
    } 
} 

$ awk -f tst.awk file 
name1 name2 name3 
    2  2  7 
    4  7  9 
    7  9 
1

Сохранить ниже скрипт:

#!/bin/bash 
gawk '{if(NR == 1) {print $2 >>"name1"; print $3 >>"name2"; print $4>>"name3";}} 
     {if($2=="A" || $2=="G"){print $1 >> "name1"}} 
     {if($3=="A" || $3=="G"){print $1 >> "name2"}} 
     {if($4=="A" || $4=="G"){print $1 >> "name3"}} 
     END{system("paste name*;rm name*")}' $1 

как finder. Сделать искатель исполняемого (используя CHMOD), а затем сделать:

./finder file.txt 

Примечание: я использовал три временные файлы name1, name2 и NAME3. Вы можете изменить имена файлов в удобное для вас время. Кроме того, эти файлы будут удалены в конце.

Редактировать: Удалить BEGIN часть gawk.

+0

Вы устанавливаете OFS, но не используете его, избыточно устанавливая ORS на значение, которое оно уже имеет, используя '>>' неверным способом, помещая условия в область действия, а не оставляя их в области условий, а в конце скрипта будет удаляться ВСЕ файлы и каталоги, начинающиеся с 'name', а не только созданные вами tmp. Есть и другие менее важные проблемы. –

+0

@ EdMorton: Спасибо за все предложения. Что касается OFS и ORS, да! Я их снял. Сначала я экспериментировал с 'printf', где я их использовал, но потом забыл удалить их, когда я изменил свое решение. Что касается временных файлов - я думаю, что у меня нет другого выбора, на самом деле именно поэтому я оставил записку в OP, предполагая, что он выберет уникальные имена файлов. , – sjsam

+0

@EdMorton: Что касается 'использования >> в неправильном направлении, ставя условия в область действия, а не оставляя их в области условий' - я не понял, что вы имели в виду. Пожалуйста, объясните это дальше. – sjsam

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