这是我的输入文件
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等。
此文件的第二个问题是它会打印连接的两个方向 在另一条线上印刷1 C 1和C 1 A 1。 这两行显示相同的关系,我不想包括这个。我想看到其中一个,即" A 1 C 1"或" C 1 A 1"不是都。 任何建议/方向都非常感谢。
答案 0 :(得分: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
创建交叉积,消除对角线和其中一对对称。
答案 1 :(得分:1)
肯定只有awk的解决方案,但我会提出一个使用awk和sort的解决方案,因为我认为这很简单,并且不需要将整个文件内容存储在awk变量中。这个想法如下:
A 1
- &gt; 1 A
)sort -n
将所有具有相同“关系”的行放在一起这会转化为:
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
编辑:如果每行只需要一个i-j关系:
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
请注意此解决方案的以下限制:
D 1
)A 1 C 1
但从不B 1 C 1
)答案 2 :(得分: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