多语句AWK脚本处理an.txt文件结果异常及匹配字符串变量化实现问询
问题分析与解决方案
一、为什么两个统计结果相同?
你的AWK脚本出现结果异常的核心原因是全局变量共用和脚本结构错误:
- AWK的执行流程是:先执行所有
BEGIN块,然后逐行处理输入文件,最后执行所有END块。你写了两个BEGIN和两个END块,但它们并不会分阶段执行——两个BEGIN都会在处理行之前运行(重复设置FS是冗余的),两个END都会在处理完所有行后运行。 - 你用了同一个变量
s来累加两个不同匹配条件的金额,导致s最终是两个条件匹配结果的总和。而两个END块打印的都是这个总和,所以结果完全相同。
修正后的脚本(分开统计)
把两个统计逻辑用不同的变量存储,合并成一个BEGIN和一个END块:
#! /usr/bin/awk -f BEGIN{ FS = "\t" } # 用不同变量分别累加 $2 ~ /Lance Te/ { lance_total += $6 } $2 ~ /Matti/ { matti_total += $6 } END{ print "Lance Te Patu: " lance_total print "Mattingly Court: " matti_total }
这样执行后,两个变量各自存储对应匹配项的总和,结果就会符合预期。
二、如何将正则匹配字符串作为变量传入脚本?
要实现灵活传递正则模式,不用在脚本中写死匹配规则,可以通过以下两种方式:
方法1:使用-v选项传递变量
通过AWK的-v参数直接将模式和对应的名称传入脚本,脚本中用变量代替硬编码的正则:
#! /usr/bin/awk -f # 接收外部传入的变量:name1, pattern1, name2, pattern2 BEGIN{ FS = "\t" } $2 ~ pattern1 { total1 += $6 } $2 ~ pattern2 { total2 += $6 } END{ print name1 ": " total1 print name2 ": " total2 }
执行时传入变量:
./b1.awk -v name1="Lance Te Patu" -v pattern1="Lance Te" -v name2="Mattingly Court" -v pattern2="Matti" an.txt
方法2:支持动态添加任意多个模式(更灵活)
如果需要支持不确定数量的匹配规则,可以通过位置参数传递模式与名称的配对,脚本中用数组存储并处理:
#! /usr/bin/awk -f BEGIN{ FS = "\t" # 处理传入的模式-名称对(格式:名称1 模式1 名称2 模式2 ... 文件名) pair_num = (ARGC - 1) / 2 # 减去最后一个文件名参数 for(i=1; i<=pair_num; i++){ name = ARGV[2*i - 1] pattern = ARGV[2*i] name_pattern[name] = pattern # 存储名称与对应的正则 # 删除已处理的参数,避免AWK把它们当作文件名 delete ARGV[2*i - 1] delete ARGV[2*i] } ARGC = 2 # 保留最后一个文件名参数 } # 逐行处理,匹配所有传入的模式 { for(name in name_pattern){ if($2 ~ name_pattern[name]){ totals[name] += $6 } } } END{ # 打印所有统计结果 for(name in totals){ print name ": " totals[name] } }
执行时可以传入任意多组规则:
./b1.awk "Lance Te Patu" "Lance Te" "Mattingly Court" "Matti" "Another Name" "Another Pattern" an.txt
这样你的脚本就完全解耦了匹配规则,不用每次修改脚本,只需在执行时传递不同的参数即可。
内容的提问来源于stack exchange,提问作者speed bump
相关产品推荐
相关产品推荐

