如何使用AWK查询加载了mapfile的文件

如何使用AWK查询加载了mapfile的文件

我在 Ubuntu 上使用 awk 来关联两个日志文件(In.log 和 Out.log)之间的引用。它按预期工作,但 Out.log 的大小增加了(~K 行),处理时间也增加了!所以我想知道,为了减少磁盘访问,我是否可以在循环之前使用 MAPFILE 命令或类似命令将此 Out.log 文件加载到内存中一次,但我没有看到有用的示例。有什么建议么?

输入日志:

2016-10-20 19:20:00,IN,DEU00000000159560100
2016-10-22 19:22:20,IN,DEU00000000159560511
2016-10-24 19:24:20,IN,DEU00000000159560382
2016-10-26 19:26:20,IN,DEU00000000159560609
2016-10-28 19:28:20,IN,DEU00000000159560809

输出日志:

2016-10-20 19:20:30,OUT,DEU00000000159560100
2016-10-21 19:21:30,OUT,DEU00000000159560510
2016-10-22 19:22:30,OUT,DEU00000000159560511
2016-10-23 19:23:30,OUT,DEU00000000159560381
2016-10-24 19:24:30,OUT,DEU00000000159560382
2016-10-25 19:25:30,OUT,DEU00000000159560195
2016-10-26 19:26:30,OUT,DEU00000000159560609
2016-10-27 19:27:30,OUT,DEU00000000159560433
2016-10-28 19:28:30,OUT,DEU00000000159560809
2016-10-29 19:29:30,OUT,DEU00000000159560694

当前脚本:

cat IN.LOG | while read -r Line
do
    Reference=$(cut -f3 -d',' <<< $Line)
    TimeStampIn=$(cut -f1 -d',' <<< $Line)
    TimeStampOut=$(awk -F',' -v Ref=$Reference '$3==Ref {print $1; exit} ' OUT.LOG)
    echo "$Reference,$TimeStampIn,$TimeStampOut"
done

答案1

只需一个awk这样的命令:

awk -v reflog=OUT.LOG '
    BEGIN{
      FS=OFS=",";
      while((getline <reflog) > 0) refs[$3]=$1;
      close(reflog)
    }{
      print $3,$1,refs[$3] ? refs[$3] : "not found"
    }' IN.LOG

或者使用join专门为这样的用例而设计的:

join -t, -j 3 -o 0,1.1,2.1 -a 1 -e "not found" \
  <(sort -t, -k3 IN.LOG) <(sort -t, -k3 OUT.LOG) \
  | sort -t, -k2

注意,join需要对输入文件进行排序(按“连接列”)。这就是为什么我们先按引用列对两个日志文件进行排序,然后再按日期对输出进行排序。

两种解决方案的行为不同关于 OUT.LOG 中的非唯一引用。awk会忽略 OUT.LOG 中的重复引用(最后一个获胜),但join会打印所有匹配项。此外,如果您添加-a 2到命令中join,它会打印全部不可配对的线路。

相关内容