我需要合并以下两个文件:
- 文件1:
表格 REF-IO HEAD-IO DIFF-IO
测试 200 500 -300
考试 2 3 -1
期末 2 1 1
邮件 4 2 2
总计 208 506 -298
- 文件2:
表格 REF-SELECT HEAD-SELECT DIFF-SELECT
测试 5 7 -2
比赛 3 3 0
考试 0 7 -7
期末 12 6 6
总计 20 23 -3
合并后的文件应如下所示:
表 REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
测试 200 500 -300 5 7 -2
考试 2 3 -1 0 7 -7
最终 2 1 1 12 6 6
邮件 4 2 2 0 0 0
合计 208 506 -298 20 23 -3
答案1
awk '
NR==FNR {vals[$1] = $2 " " $3 " " $4; next}
!($1 in vals) {vals[$1] = "0 0 0"}
{$(NF+1) = vals[$1]; print}
' file2 file1
TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
test 200 500 -300 5 7 -2
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
TOTAL 208 506 -298 20 23 -3
答案2
以下是如何使用join
并保留行顺序、页眉、页脚等......
join -1 2 -2 1 -a 1 -e 0 -o 1.1,1.2,1.3,1.4,1.5,2.2,2.3,2.4 \
<(sort -k2,2 <(nl -ba -nrz file1)) <(sort -k1,1 file2) | \
sort -k1,1n | cut -d\ -f2-
结果:
TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
test 200 500 -300 5 7 -2
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
TOTAL 208 506 -298 20 23 -3
怎么运行的:
nl -ba -nrz file1
对 中的行进行编号file1
,然后将输出sort
添加到第二个字段;file2
也在sort
第一个字段上进行编辑,然后将结果join
在第一个输入的第二个字段和第二个输入的第一个字段上进行编辑,将丢失的输入字段替换为0
:
000003 exam 2 3 -1 0 7 -7
000004 final 2 1 1 12 6 6
000005 mail 4 2 2 0 0 0
000001 TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
000002 test 200 500 -300 5 7 -2
000006 TOTAL 208 506 -298 20 23 -3
然后在第一个字段上排序以sort -k1,1n
恢复行顺序,然后cut -d\ -f2-
删除行号。您可以使用例如进一步美化column
它.... | column -t
:
TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
test 200 500 -300 5 7 -2
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
TOTAL 208 506 -298 20 23 -3
答案3
这个脚本应该可以工作:
touch resultFile
while read f; do
header1=$(echo $f | awk '{print $1;}');
values1=$(echo $f | awk -F "$header1 " '{print $NF;}');
while read g; do
header2=$(echo $g | awk '{print $1;}');
values2=$(echo $g | awk -F "$header2 " '{print $NF;}');
if [ $header1 = $header2 ]; then
echo "$header1 $values1 $values2" >> resultFile
fi
done < file2
done < file1
标头必须是唯一的,否则只会合并找到的最后一行。
PS:我认为“邮件”标头不应出现在结果中,因为它不存在于两个文件中,因为“游戏”(在您的示例中存在“邮件”但不存在“游戏”)。
答案4
如果您想知道,它是join
尽管不保留行的顺序,但可以使用 执行此操作:
(
join <(head -n1 file1) <(head -n1 file2)
join -a 1 -e 0 -o '0 1.2 1.3 1.4 2.2 2.3 2.4' \
<(sed -n 2,5p file1 | sort) \
<(sed -n 2,5p file2 | sort)
join <(tail -n1 file1) <(tail -n1 file2)
)
输出:
TABLES REF-IO HEAD-IO DIFF-IO REF-SELECT HEAD-SELECT DIFF-SELECT
exam 2 3 -1 0 7 -7
final 2 1 1 12 6 6
mail 4 2 2 0 0 0
test 200 500 -300 5 7 -2
TOTAL 208 506 -298 20 23 -3