2017-02-17 22 views
3

У меня есть большая табуляция два файла столбец, который имеет координаты многих биохимических путей, как это:Как объединить строки в файле на основе общих полей с помощью awk?

A B 
B D 
D F 
F G 
G I 
A C 
C P 
P R 
A M 
M L 
L X 

Я хочу, чтобы объединить строки, если столбец 1 в одной строке равна колонке 2 в другой линии, в результате следующий вывод:

A B D F G I 
B D F G I 
D F G I 
F G I 
G I 
A C P R 
C P R 
P R 
A M L X 
M L X 
L X 

Я хотел бы использовать что-то простое, такие как AWK 1 лайнер, есть ли какое-либо идеи, как я бы подойти к этому без написания скрипта? Любая помощь приветствуется. Я пытаюсь получить каждый шаг и каждый последующий шаг в каждом пути. Поскольку эти пути часто пересекаются, некоторые шаги разделяются другими путями, но я хочу анализировать каждый отдельно.

Я попробовал скрипт, где я пытаюсь Grep любого столбца, где $ 2 = $ 1 в конце файла:

while [ -s test ]; do 
    grep -m1 "^" test > i 
    cut -f2 i | sed 's/^/"/' | sed 's/$/"/' | sed "s/^/awk \'\$1 == /" | sed "s/$/' test >> i/" > i.sh 
    sh i.sh 
    perl -p -e 's/\n/\t/g' i >> OUT 
    sed '1d' test > i ; mv i test 
done 

Я знаю, что моя проблема исходит от (а) удаления строки и (б) факт наличия дубликатов. Я просто не знаю, как это решить.

+0

Я пытался писать скрипт, который принимает строку в файле, выбирает столбец 2, отбирает из каждой строки, где значение == столбец 1, но моя проблема в том, что она отбирает (очевидно) и не делает надежную «карту» – Oddish

+0

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

+0

Можете ли вы объяснить с помощью примера, как генерируется вывод из этого ввода? Не ясно (по крайней мере для меня) – Inian

ответ

3

Входной

$ cat f 
A B 
B D 
D F 
F G 
G I 
A C 
C P 
P R 
A M 
M L 
L X 

Выходной

$ awk '{ 
     for(j=1; j<=NF; j+=2) 
     { 
      for(i=j;i<=NF;i+=2) 
      { 
       printf("%s%s", i==j ? $i OFS : OFS,$(i+1)); 
       if($(i+1)!=$(i+2)){ print ""; break } 
      } 
      } 
     }' RS= OFS="\t" f 
A B D F G I 
B D F G I 
D F G I 
F G I 
G I 
A C P R 
C P R 
P R 
A M L X 
M L X 
L X 

Один лайнер

awk '{ for(j=1; j<=NF; j+=2)for(i=j;i<=NF;i+=2){printf("%s%s", i==j ? $i OFS : OFS,$(i+1)); if($(i+1)!=$(i+2)){ print ""; break }}}' RS= OFS="\t" f 
+1

Хороший, достойный' ++ ' – Inian

0

Ну, вы могли бы поставить это на одной линии, но я бы не рекомендовал его :)

#!/usr/bin/awk -f 

{ 
    a[NR] = $0 

    for(i = 1; i < NR; i++){ 
    if(a[i] ~ $1"$") 
     a[i] = a[i] FS $2 
    if(a[i] ~ "^"$1){ 
     for(j = i; j < NR; j++){ 
     print a[j] 
     delete a[j] 
     } 
    } 
    } 
} 

END{ 
    for(i = 1; i <= NR; i++) 
    if(a[i] != "") 
     print a[i] 
} 
0
$ <f.txt tac | awk 'BEGIN{OFS="\t"}{if($2==c1){$2=$2"\t"c2};print $1,$2;c1=$1;c2=$2}' | tac 
A  B  D  F  G  I 
B  D  F  G  I 
D  F  G  I 
F  G  I 
G  I 
A  C  P  R 
C  P  R 
P  R 
A  M  L  X 
M  L  X 
L  X