2015-10-26 49 views
2

这里是我的输入文件如何做一个加入用awk

Identifier Relation 
A   1 
A   2 
A   3 
B   2 
B   3 
C   1 
C   2 
C   3 

我想基于“关系”字段加入这一文件本身。 样本输出文件

A 1 C 1 
A 2 B 2 
A 2 C 2 
B 2 C 2 
A 3 B 3 
A 3 C 3 
B 3 C 3 

我用下面的awk脚本: awk 'NR==FNR {a[NR]=$0; next} { for (k in a) if (a[k]~$2) print a[k],$0}' input input > output

然而,我不得不做另一个AWK步骤删除其做了与本身即一个连接线,A 1 A 1; B 2 B 2等

该文件的第二个问题是它打印连接的两个方向,因此 A 1 C 1与另一行上的C 1 A 1一起打印。 这两个线显示相同的关系,我不希望包括this.I想看到的只是一个或另一个即,“A 1 C 1”或“C 1 A 1”不能同时使用。 任何建议/方向高度赞赏。

回答

1

下面是一个AWK-唯一的解决办法:

awk 'NR>1{ar[$2]=(ar[$2]$1);}\ 
    END{ for(key in ar){\ 
     for(i=1; i<length(ar[key]); i++) {\ 
      for(j=i+1; j<length(ar[key])+1; j++) {\ 
       print substr(ar[key],i,1), key, substr(ar[key],j,1), key;\ 
      }\ 
     }\ 
    }}' infile 

input的第二列中的每个号码用作AWK-阵列的密钥。相应的数组元素的值是第一列字母(例如,阵列[1] = ABC)的序列。

然后,我们构建的所有两个字母的组合对于每个序列(例如, “ABC” 给出

输出 “AB”, “AC” 和 “BC”):

A 1 C 1 
A 2 B 2 
A 2 C 2 
B 2 C 2 
A 3 B 3 
A 3 C 3 
B 3 C 3 

注:

  • 如果只发生一次的数,被用于产生输出这个号码。
  • 输出的顺序取决于输入的顺序。 (没有字母排序!!)。也就是说,如果第二输入线是C 1,然后array[1]="CAB"和第一输出线将是C 1 A 1
  • 输入的第一行被忽略由于NR>1
1

确实只有awk的解决方案,但是我会提出一个使用awk和排序的解决方案,因为我认为它很简单,并且不需要将整个文件内容存储在awk变量中。这个想法如下:

  • 重写输入文件,使“关系”场是第(A 1 - >1 A
  • 使用sort -n所有线放在一起以相同的“关系”
  • 使用AWK结合具有相同的“关系”

这将转化为类似连续行:

awk '{print $2 " " $1}' input | sort -n | 
    awk '{if ($1==lastsel)printf " "; else if(lastsel) printf "\n"; lastsel=$1; printf "%s %s", $2, $1;}END{if(lastsel)printf"\n"}' 
A 1 C 1 
A 2 B 2 C 2 
A 3 B 3 C 3 

编辑:如果您想每行只有一个IJ关系:

awk '{print $2 " " $1}' input | sort -n | 
    awk '$1!=rel{rel=$1;item=$2;next;} {printf "%s %s %s %s\n", item, rel, $2, $1;}' 
A 1 C 1 
A 2 B 2 
A 2 C 2 
A 3 B 3 
A 3 C 3 

注意与此解决方案有以下限制:

  • 如果一个给定的n只有一个入口,没有将被输出(没有输出,例如D 1
  • 所有关系在第一列中总是具有词典上的第一项(例如A 1 C 1但从未B 1 C 1
+0

非常感谢回复@secolive !!!但是,我想我的输出如下:A 1 C 1; A 2 B 2; A 2 C 2; B 2 C 2;等等。因此,每个组合在不同的线上,不是一起附加在一行中。 – scout

+0

确实;相应地编辑帖子 – secolive

2

替代的解决方案使用AWK与加入和排序支持

$ join -j 2 <(sort -k2 -k1,1 file){,} 
| awk '$2!=$3 && !($3 FS $2 in a){a[$2 FS $3]; print$2,$1,$3,$1}' 
A 1 C 1 
A 2 B 2 
A 2 C 2 
B 2 C 2 
A 3 B 3 
A 3 C 3 
B 3 C 3 

创建叉积,消除对角线和其中一个对称对。