You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本用awk筛选同firm下时间差小于30秒的3条及以上CSV记录

awk实现CSV分组连续时间差筛选方案

需求规则

处理orders.csv文件,提取符合以下要求的记录:

  • 按第三列firm字段分组,仅保留分组总记录数≥3的firm相关记录
  • 同一firm下的记录按文件原始顺序排列,相邻记录第二列time字段时间差小于30秒的记录保留,时间差≥30秒的记录排除
  • 若同一firm下存在多段满足「相邻差<30秒且段内记录数≥3」的连续序列,输出第一段或全部符合段的记录均可。

样例输入

orders.csv格式:

date,time,firm,user,id
20220520,12:00:00,TEST1,ABC,FNT0060
20220520,12:00:05,TEST2,ABC,FNT0061
20220520,12:00:10,TEST1,ABC,FNT0062
20220520,12:00:25,TEST1,ABC,FNT0063
20220520,12:00:45,TEST1,ABC,FNT0064
...

预期输出

date,time,firm,user,id
20220520,12:00:00,TEST1,ABC,FNT0060
20220520,12:00:10,TEST1,ABC,FNT0062
20220520,12:00:25,TEST1,ABC,FNT0063

已实现的零散逻辑

  1. 全局时间差计算(未按firm分组,存在逻辑缺陷):
awk -F '[:,]' '{t=$2*3600+$3*60+$4} NR>1{printf( "%.6f\n", t-p)}{p=t}' $orders.csv > abc.csv

注:原命令中x为笔误,awk乘法运算符为*
2. 筛选记录数≥3的firm全量记录(未做时间差过滤):

awk -F',' 'NR==FNR{cnt[$3]++; next} cnt[$3]>=3' $orders.csv $orders.csv > firm.csv

完整实现命令

无需生成中间文件,单次执行awk双遍历即可完成所有逻辑,直接输出结果:

awk -F',' '
# 第一遍遍历:统计每个firm的总记录数,过滤记录数不足3的分组
NR==FNR {
    if (NR>1) firm_cnt[$3]++
    next
}
# 输出CSV表头
FNR==1 {
    print $0
    next
}
# 跳过总记录数不足3的firm记录
firm_cnt[$3] < 3 { next }
{
    # 拆分time字段为秒级时间戳,方便计算差值
    split($2, time_arr, ":")
    cur_sec = time_arr[1]*3600 + time_arr[2]*60 + time_arr[3]

    # 首次处理该firm,初始化连续段缓存
    if (!($3 in last_sec)) {
        seg_len[$3] = 0
        delete seg_cache[$3]
    } else {
        time_diff = cur_sec - last_sec[$3]
        # 时间差≥30秒,触发连续段断点检查
        if (time_diff >= 30) {
            # 当前连续段长度≥3,输出段内所有记录
            if (seg_len[$3] >= 3) {
                for (i=1; i<=seg_len[$3]; i++) print seg_cache[$3,i]
                # 若需要仅输出每个firm的第一个符合条件段,取消下一行注释即可
                # output_done[$3] = 1
            }
            # 清空连续段缓存,开始新段统计
            seg_len[$3] = 0
            delete seg_cache[$3]
        }
    }

    # 该firm已输出过符合要求的段,直接跳过后续缓存逻辑
    if (output_done[$3]) {
        last_sec[$3] = cur_sec
        next
    }

    # 当前记录加入连续段缓存
    seg_len[$3]++
    seg_cache[$3, seg_len[$3]] = $0
    last_sec[$3] = cur_sec
}
# 遍历结束后检查所有firm最后一段未触发断点的缓存
END {
    for (f in firm_cnt) {
        if (output_done[f]) continue
        if (seg_len[f] >= 3) {
            for (i=1; i<=seg_len[f]; i++) print seg_cache[f,i]
        }
    }
}
' orders.csv orders.csv

逻辑说明

  • 双遍历逻辑和已实现的firm计数逻辑一致,第一遍仅做分组计数,第二遍才做实际过滤处理
  • 时间差计算严格按firm分组独立统计,不会被其他firm的记录打断连续段计算
  • 默认输出所有符合长度要求的连续段,如需仅输出第一个符合段,按注释打开对应行即可
  • 所有计算基于秒级时间戳,不存在跨小时、跨分钟的计算错误

内容的提问来源于stack exchange,提问作者Ad Il

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:54:31