AWK如何基于已有列按跨行规则新增分组标识列
AWK跨行比较实现方案
你可以直接使用以下代码完成需求:
awk -F '|' ' # 日期转天数函数,用于计算间隔 function date2days(d, t, y, m, day) { split(d, t, "-") y = t[1]+0; m = t[2]+0; day = t[3]+0 return mktime(y " " m " " day " 0 0 0") / 86400 } BEGIN { OFS = "|" gid = 1 # 分组序号从1开始 } { # 缓存当前行关键字段 cur_name = $1 cur_3 = $3 cur_4 = $4 cur_7 = $7 + 0 cur_8 = $8 # 存在上一行缓存、且两行属于同一个$1分组、$3均非空时才判断 if (prev_name != "" && prev_name == cur_name && prev_3 != "" && cur_3 != "") { # 计算日期差 delta = date2days(prev_5) - date2days(cur_4) # 依次计算所有条件 cond1 = (delta >= 0 && delta <= 2) cond2 = (prev_6 == 51) cond3 = (cur_7 == 51) cond4 = (cur_8 == "2B" || cur_8 == "41") cond5 = (prev_6 == 19 && cur_7 == 51 && cur_8 == "21") # 符合条件则给上一行加分组标识 if (cond1 && (cond2 || cond3 || cond4) && !cond5) { prev_line = prev_line "|group" gid++ } # 输出处理完成的上一行 print prev_line } else if (prev_name != "") { # 分组变化时直接输出上一行缓存 print prev_line } # 将当前行缓存为下一次比较的上一行 prev_name = cur_name prev_3 = cur_3 prev_5 = $5 prev_6 = $6 + 0 prev_line = $0 } END { # 输出最后一行没有后续行比较的内容 print prev_line } ' 你的输入文件路径
说明
- 代码核心逻辑是缓存前一行的完整内容和关键字段,读入新行后先完成两行的匹配判断,处理完前一行再输出,再将当前行更新为缓存,实现跨行比较。
- 如果运行时提示
mktime不存在,说明你使用的是BSD版本awk,安装GNU awk(gawk)即可正常运行。 - 代码输出和你给出的预期结果完全一致。
内容的提问来源于stack exchange,提问作者DSTO
相关产品推荐
相关产品推荐

