我有两个文件,我使用下面的代码
基于密钥合并它们file1
-------------------------------
1 a t p bbb
2 b c f aaa
3 d y u bbb
2 b c f aaa
2 u g t ccc
2 b j h ccc
file2
--------------------------------
1 11 bbb
2 22 ccc
3 33 aaa
4 44 aaa
我使用下面的代码
合并了这两个基于文件的密钥awk 'NR==FNR{a[$3]=$0;next;}{for(x in a){if(x==$5) print $1,$2,$3,$4,a[x]};
我的问题是如何在变量或数组中保存$ 2的file2并再次在[x]之后打印 我想要的结果是:
1 a t p 1 11 bbb 11
2 b c f 3 33 aaa 33
2 b c f 4 44 aaa 44
3 d y u 1 11 bbb 11
2 b c f 3 33 aaa 33
2 b c f 4 44 aaa 44
2 u g t 2 22 ccc 22
2 b j h 2 22 ccc 22
如您所见,前7列是我的合并代码的结果。我需要将最后一列([x]的字段2)添加到我的结果中。
重要的:
我的下一个问题是,如果我有.awk文件,如何使用像(| column -t
)这样的bash脚本代码或将结果发送到文件(awk... > result.txt
)?我总是在命令提示符下使用这些代码。我可以在.awk文件中的代码中使用它们吗?
答案 0 :(得分:3)
您当前的脚本是:
awk 'NR==FNR { a[$3]=$0; next }
{ for (x in a) { if (x==$5) print $1,$2,$3,$4,a[x] } }'
(实际上,原始版本缺少第二个模式/动作对的第二个大括号。)
您似乎在处理file2
之前处理file1
。
你不应该在第二个代码中需要循环。通过在第一阶段使用拆分来保持您需要的值,您可以让自己的生活更轻松:
awk 'NR==FNR { c1[$3] = $1; c2[$3] = $2; next }
{ print $1, $2, $3, $4, c1[$5], c2[$5], $5, c2[$5] }'
您可以升级它以检查是否已定义c1[$5]
和c2[$5]
,如果不是,则可能会跳过该行。
根据输入文件,输出为:
1 a t p 1 11 bbb 11
2 b c f 4 44 aaa 44
3 d y u 1 11 bbb 11
2 b c f 4 44 aaa 44
2 u g t 2 22 ccc 22
2 b j h 2 22 ccc 22
提供或获取列间距,这就是请求的内容。可以使用printf
代替print
,或将OFS设置为标签,或...来修复列间距。
第1列和第2列的c1
和c2
符号对于两列是正常的。如果您需要更多,那么您应该使用2D数组表示法:
awk 'NR==FNR { for (i = 1; i <= NF; i++) col[i,$3] = $i; next }
{ print $1, $2, $3, $4, col[1,$5], col[2,$5], $5, col[2,$5] }'
这产生与以前相同的输出。
答案 1 :(得分:3)
只需将所有file2
添加到数组中,然后使用split
保存所需的位:
awk 'FNR==NR { two[$0]++; next } { for (i in two) { split(i, one); if (one[3] == $NF) print $1,$2,$3,$4, i, one[2] } }' file2 file1
结果:
1 a t p 1 11 bbb 11
2 b c f 3 33 aaa 33
2 b c f 4 44 aaa 44
3 d y u 1 11 bbb 11
2 b c f 3 33 aaa 33
2 b c f 4 44 aaa 44
2 u g t 2 22 ccc 22
2 b j h 2 22 ccc 22
关于你的上一个问题;您还可以在awk
内添加“管道”和“写入”。以下是column -t
的管道示例:
script.awk
的内容:
FNR==NR {
two[$0]++
next
}
{
for (i in two) {
split(i, one)
if (one[3] == $NF) {
print $1,$2,$3,$4, i, one[2] | "column -t"
}
}
}
运行方式:awk -f script.awk file2 file1
<强> 编辑: 强>
将以下内容添加到shell脚本中:
results=$(awk '
FNR==NR {
two[$0]++
next
}
{
for (i in two) {
split(i, one)
if (one[3] == $NF) {
print $1,$2,$3,$4, i, one[2] | "column -t"
}
}
}
' $1 $2)
echo "$results"
运行如:
./script.sh file2.txt file1.txt
结果:
1 a t p 1 11 bbb 11
2 b c f 3 33 aaa 33
2 b c f 4 44 aaa 44
3 d y u 1 11 bbb 11
2 b c f 3 33 aaa 33
2 b c f 4 44 aaa 44
2 u g t 2 22 ccc 22
2 b j h 2 22 ccc 22
答案 2 :(得分:2)
要实现您的要求,请使用a[$3]=$0 OFS $2
在处理第一个文件的整行后保存第二个字段。对于您的第二个问题,awk
有一个变量来分隔输出中的字段,它是OFS
,为其分配制表符并使用它。你的脚本就像:
awk '
BEGIN { OFS = "\t"; }
NR==FNR{
a[$3]=$0 OFS $2;
next;
}
{
for(x in a){
if(x==$5) print $1,$2,$3,$4,a[x]
}
}
' file2 file1
产量:
1 a t p 1 11 bbb 11
2 b c f 4 44 aaa 44
3 d y u 1 11 bbb 11
2 b c f 4 44 aaa 44
2 u g t 2 22 ccc 22
2 b j h 2 22 ccc 22