如何使用awk进行连接
这是我的输入文件如何使用awk进行连接,awk,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==FN
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(a中的k)如果(a[k]~$2)打印a[k],$0}'输入>输出
然而,我不得不做另一个awk步骤来删除与自身连接的行,即a1;b2b2等
该文件的第二个问题是它打印连接的两个方向,因此
与C1 A1一起打印在另一行上。
这两行显示相同的关系,我不想包括这一行。我只想看到其中一行,即“A1 C1”或“C1 A1”,而不是两者。
非常感谢您的任何建议/指导。肯定有一个仅使用awk的解决方案,但我将提出一个使用awk和排序的解决方案,因为我认为它非常简单,不需要将整个文件内容存储在awk变量中。其思路如下:
- 重写输入文件,使“关系”字段位于第一位(
->a1
)1a
- 使用
将具有相同“关系”的所有行放在一起排序-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
编辑:如果每行只需要一个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
请注意此解决方案的以下限制:
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
- 如果给定的n只有一个条目,则不会输出任何内容(没有输出,例如
)d1
- 所有关系在第一列中都始终有按字典顺序排列的第一项(例如
,但决不a1c1
)b1c1
- 以下是一个仅适用于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
注:
- 如果一个数字只出现一次,则不会为该数字生成输出
- 输出的顺序取决于输入的顺序。(没有字母排序!!)。也就是说,如果第二个输入行是
,那么c1
,第一个输出行将是array[1]=“CAB”
c1a1
- 由于
NR>1
$ 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
$join-j2非常感谢@secolive的回复!!!然而,我希望我的输出如下:a1c1;a2b2;a2c2;b2c2;因此,每个组合在不同的行上,而不是附加在一行中。