【问题标题】:awk statements - if not found (grep'ed) doawk 语句 - 如果没有找到(grep'ed)做
【发布时间】:2013-06-13 18:56:28
【问题描述】:

我的表格文件示例如下所示

Name1   xxxxx  34
Name1   xxxxx  37
Name2   aaaaa  59
Name2   xxxxx  90
Name4   Name3  12

名称文件看起来像这样

Name1 
Name2
Name3
Name4 

我希望 awk 将名称文件中的 Name1/2/3/4 匹配到表文件 $1 并打印 $3 的总和。 如果找不到姓名打印 0 - 我怎么能在awk 中做这样的if 声明?

我已经做了什么:

for i in $(cat Name_file)
do 
cat table | awk -v NAME="$i" '($1==NAME) {SUM+=$3} END {print NAME"\t"SUM}'
done

给出输出

Name1   71
Name2   149
Name3   
Name4   12

几乎完美 - 我想将 0 添加到 Name3 以获得这样的输出

Name1   71
Name2   149
Name3   0
Name4   12

这么多问题是:如何在awk中添加if not found do函数?

【问题讨论】:

  • 我可能会建议在bash 中使用$(<file) 而不是$(cat file)。第一种表示法不调用外部实用程序。也使用awk '...' file 而不是cat file | awk '...'
  • 你的意思是for i in $(< Name_file)?你的建议和while read WORD; do command ; done < Name_file有什么区别?
  • 是的,使用$(<Name_file)。它是$(cat Name_file) 的内部bash 快捷方式。所以它不会调用cat,只是打开文件。 read内部函数读取<file重定向到while的文件。 Read 可以将多个单词读取到多个变量或数组中。

标签: awk


【解决方案1】:

Y 不需要任何“未找到”行为。在计数之前,您只是没有正确初始化 SUM 变量。为此使用BEGIN {SUM = 0}

如果您明确需要找到/未找到的行为,请以类似方式执行。首先,初始化一些变量BEGIN {FOUND = 0},然后在模式匹配上以某种方式改变它:(...) {FOUND = FOUND+1},最后用if(FOUND!=0)进行测试。

【讨论】:

    【解决方案2】:

    像这样尝试 sg:

    awk 'NR==FNR{a[$1]=0;next}$1 in a{a[$1]+=$3}END{for(i in a) print i,a[i]}' Name_file table
    

    输出:

    Name1 71
    Name2 149
    Name3 0
    Name4 12
    

    在这种情况下,您不需要围绕 循环。它首先读取Names_table,然后一步处理table 的所有行。所以它更有效。

    添加

    或纯 (>= 4.0) 解决方案:

    printf -v tmp "[%s]=0 " $(<Name_file)
    declare -A htmp
    eval htmp=($tmp)
    while read a b c; do [ -n "${htmp[$a]}" ] && ((htmp[$a] += $c)); done <table
    for i in ${!htmp[*]}; do echo $i ${htmp[$i]}; done
    

    扩展

    扩展的问题是按$1$2 分组(并且Name_file 包含来自table 的所有第一个键,因此实际上不需要处理)。

    cat >table <<XXX
    Name1   xxxxx  34
    Name1   xxxxx  37
    Name2   aaaaa  59
    Name2   xxxxx  90
    Name4   Name3  12
    XXX
    
    awk -v SUBSEP=, '{a[$1,$2]+=$3;++n[$1,$2]}END{for(i in a) print i,a[i],n[i]}' table
    

    输出:

    Name2,xxxxx 90 1
    Name2,aaaaa 59 1
    Name4,Name3 12 1
    Name1,xxxxx 71 2
    

    【讨论】:

    • 您的方法将打印所有行的总和,而不仅仅是列在名称中。您应该添加($1 in a) 条件才能正常工作。它还会以可能不需要的随机顺序打印计数。
    • @Vovanium:谢谢!添加。实际上它不在规范中...... :)
    • @PaulGardir:当然!您可以使用(伪)二维数组,例如a[$1,$2]。那么Name_file 数组真的需要吗?什么,如果table 中有一行$1 不是Name_file?应该跳过吗?
    • @PaulGardir:那我不明白你原来的问题! table 中没有密钥怎么会发生?
    • @PaulGardir:我为您的另一个问题添加了一个可能的解决方案。我希望我能很好地解释您的评论。
    猜你喜欢
    • 2012-11-19
    • 2020-10-16
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多