【问题标题】:how to perform a key field lookup in a file using bash or awk?如何使用 bash 或 awk 在文件中执行关键字段查找?
【发布时间】:2016-05-27 16:57:33
【问题描述】:

我是 shell 脚本和 awk 的新手。任何人都可以建议一个更有效和更优雅的解决方案来解决我在下面执行的两个文件之间的关键查找吗?

两个输入文件:

文件 1 - 包含单列键字段 (server-metricname-minute):

key_column  
server026-AckDelayAverage-00:01:00  
server026-AckDelayMax-00:01:00  
server026-AckSent-00:01:00  
server026-DigEnvValidationLatestTime-00:01:00  
server026-DigEnvValidationTimeAverage-00:01:00

文件 2 - 逗号分隔,包含关键字段和其他字段的数量

key_column,host,date,minute,metricname, metric value  
server026-AckDelayAverage-00:01:00,server026,May 24 2016,00:01:00,AckDelayAverage,942  
server026-AckDelayMax-00:01:00,server026,May 24 2016,00:01:00,AckDelayMax,5855  
server026-AckSent-00:01:00,server026,May 24 2016,00:01:00,AckSent,49038  

我的逻辑是:

Loop through file1  
If key found in File2  
    print file1.key , file2.field3 , file2.field6 to file3  
else  
    print file1.key + 'KEY_NOT_FOUND' text to file3  
fi    

所以 file3 的输出应该为 file1 中的每条记录都有一行。

下面的代码似乎可以工作,但是任何人都可以提出一种更有效和更优雅的方法来实现这一点吗?

while read key ;  
do  
        metric_found=`grep $key file2`  
    if [[ ! -z $metric_found ]]  
    then  
            echo ${metric_found} | awk -F "," '{print $1",$3,"$6}'  
    else  
            echo ${key},KEY_NOT_FOUND  
    fi  
done < file1  

基于示例数据的现有脚本的示例输出:

server026-AckDelayAverage-00:01:00,May 24 2016,942  
server026-AckDelayMax-00:01:00,May 24 2016,5855  
server026-AckSent-00:01:00,May 24 2016,49038  
server026-DigEnvValidationLatestTime-23:59:00,KEY_NOT_FOUND  
server026-DigEnvValidationTimeAverage-23:59:00,KEY_NOT_FOUND  

谢谢..

【问题讨论】:

  • 如果您只是在寻找一般的 cmets 和改进,您的问题可能更适合代码审查网站
  • 请阅读 why-is-using-a-shell-loop-to-process-text-considered-bad-practice 以了解您应该为此使用 awk 而不是 shell 循环的一些原因。
  • 感谢您的文章。信息量很大。从现在开始,我将使用 awk 进行此类处理。

标签: linux shell awk


【解决方案1】:

试试这个:

awk 'BEGIN{FS=OFS=","}NR==FNR{a[$1]=1;b[$1]=$3;c[$1]=$6;}NR>FNR{if (a[$1]) print $1,b[$1],c[$1]; else print $1,"KEY_NOT_FOUND";}' file2 file1 > file3

【讨论】:

  • 谢谢,您能解释一下这是如何工作的吗?
【解决方案2】:
$ cat tst.awk
BEGIN { FS=OFS="," }
NR==FNR { file2[$1] = $3 OFS $6; next }
FNR>1 { print $1, ($1 in file2 ? file2[$1] : "KEY_NOT_FOUND") }

$ awk -f tst.awk file2 file1
server026-AckDelayAverage-00:01:00,May 24 2016,942
server026-AckDelayMax-00:01:00,May 24 2016,5855
server026-AckSent-00:01:00,May 24 2016,49038
server026-DigEnvValidationLatestTime-00:01:00,KEY_NOT_FOUND
server026-DigEnvValidationTimeAverage-00:01:00,KEY_NOT_FOUND

【讨论】:

  • 谢谢。根据我的理解,您能否解释一下第 2 行和第 3 行?
  • NR==FNR 仅适用于第一个文件,因此第 2 行填充了一个关联数组,将 file1 中的每个第一个字段值映射到同一行的第二个和第三个字段。第 3 行仅使用三元表达式打印由 file2 中的第一个字段索引的 file1 数组的内容。我强烈推荐 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书。
猜你喜欢
  • 1970-01-01
  • 2014-08-20
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 2022-11-27
  • 2016-12-11
  • 1970-01-01
相关资源
最近更新 更多