cat Error00
4 0 375
4 2001 21
4 2002 20
cat Error01
4 0 465
4 2001 12
4 2002 40
4 2016 1
我想要输出如下
4 0 375 465
4 2001 21 12
4 2002 20 20
4 2016 - 1
我正在使用以下查询。这里的问题是我无法处理两个字段的grep因为空间即将到来。 请建议如何摆脱这个。
keylist=$(awk '{print $1,$2'} Error0[0-1] | sort | uniq)
for key in ${keylist} ; do
echo ${key}
val_a=$(grep "^${key}" Error00 | awk '{print $3}') ;val_a=${val_a:---}
val_b=$(grep "^${key}" Error01 | awk '{print $1,$2}') ; val_b=${val_b:--- --}
echo $key ${val_a} >>testreport
done
我将oputput设置如下
4 375 465
0
4 21 12
2001
4 20 20
2002
4 - 1
2016
答案 0 :(得分:4)
单个awk
一个班轮可以轻松处理这个问题:
awk 'FNR==NR{a[$1,$2]=$3;next}{print $1,$2,(a[$1,$2]?a[$1,$2]:"-"),$3}' err0 err1
4 0 375 465
4 2001 21 12
4 2002 20 40
4 2016 - 1
对于格式化输出,您可以使用printf
代替print
。像Jonathan Leffler建议:
printf "%s %-6s %-6s %s\n",$1,$2,(a[$1,$2]?a[$1,$2]:"-"),$3
4 0 375 465
4 2001 21 12
4 2002 20 40
4 2016 - 1
然而,一般的解决方案是使用column -t
作为一个很好的表输出:
awk '{....}' err0 err1 | column -t
4 0 375 465
4 2001 21 12
4 2002 20 40
4 2016 - 1
答案 1 :(得分:1)
grep
并非真正适合这项工作的工具。您可以使用awk
或Perl(或Python,或......),也可以使用join
。但是,join
一次只能连接一个列,并且您似乎需要连接两列。因此,我们将不得不按摩数据,以便它可以与join
一起使用。我将假设您正在使用bash
,因此process substitution可用。你可以在没有这项工作的情况下完成这项工作,但它更加繁琐,并且涉及临时文件(以及用于清理它们的陷阱等)。
连接的关键是用冒号(或任何其他方便的字符替换前两列之间的空白 - control-A也能正常工作),然后用第1列的文件加入替换字符。必须对输入进行排序;输出必须用空格替换冒号。
$ join -o 0,1.2,2.2 -a 1 -a 2 -e '-' \
> <(sed 's/ */:/' Error00 | sort) \
> <(sed 's/ */:/' Error01 | sort) |
> sed 's/:/ /'
4 0 375 465
4 2001 21 12
4 2002 20 40
4 2016 - 1
$
's/ */:/'
操作用冒号替换一个或多个空格的第一个序列;输入数据在Error00
的第一行中的4和0之间有两个空格。 join
的输入必须按加入字段的排序顺序排列,此处为第一个字段。输出是连接字段,Error00
的第二列和Error01
的第二列(记住这意味着前两个列之后的第二列已被冒号融合)。如果第一个文件中有不匹配的行,则生成输出行(-a 1
);同上第二个文件;对于缺少的字段,插入破折号(-e '-'
)。最后的sed
删除了添加的冒号。
如果您希望格式化数据,请通过awk
。
$ join -o 0,1.2,2.2 -a 1 -a 2 -e '-' \
> <(sed 's/ */:/' Error00 | sort) \
> <(sed 's/ */:/' Error01 | sort) |
> sed 's/:/ /' |
> awk '{printf("%s %-6s %-6s %s\n", $1, $2, $3, $4)}'
4 0 375 465
4 2001 21 12
4 2002 20 40
4 2016 - 1
$