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

如何用Linux脚本合并时间序列数据中同时间的多行记录?

问题描述

我有一份多传感器异步采集后拼接的ASCII格式时间序列数据,同时间点的传感器值分散在多行,以空格分隔。原始数据示例如下:

2022 281 08 48 14 876 10                1.00       NOTSAMPLED          NOTSAMPLED
2022 281 08 48 14 876 10          NOTSAMPLED             0.00          NOTSAMPLED
2022 281 08 48 14 876 10          NOTSAMPLED       NOTSAMPLED                1.00
2022 281 08 48 15 391 11                1.00       NOTSAMPLED          NOTSAMPLED
2022 281 08 48 15 391 11          NOTSAMPLED             0.00          NOTSAMPLED
2022 281 08 48 15 391 11          NOTSAMPLED       NOTSAMPLED                1.00
2022 281 08 48 15 896 12                1.00       NOTSAMPLED          NOTSAMPLED
2022 281 08 48 15 896 12          NOTSAMPLED             0.00          NOTSAMPLED
2022 281 08 48 15 896 12          NOTSAMPLED       NOTSAMPLED                1.00

需求如下:

  1. 将字符串NOTSAMPLED替换为对应传感器的前序有效值
  2. 将同时间点分散在多行的传感器值合并为单行

预期输出示例如下:

2022 281 08 48 14 876 10                1.00       0.0     1.0
2022 281 08 48 15 391 11                1.00       0.0     1.0
2022 281 08 48 15 896 12                1.00       0.0     1.0

我尝试了如下脚本,但结果不符合预期:

#! /bin/bash

inp_filename=$1

awk '
NR == 1 { split($0, filldown) }
{
 for (i = 6; i <= NF; i++)
  if ($i != "NOTSAMPLED")
   filldown[i] = $i
 else
   $i = filldown[i]
 print
}
' $inp_filename
解决方案

可以用awk实现,核心逻辑是按时间点分组,收集每个传感器的有效值,最后合并输出单行数据。脚本如下:

#!/usr/bin/awk -f

# 生成时间唯一键(前7个字段)
function get_time_key() {
    return $1 FS $2 FS $3 FS $4 FS $5 FS $6 FS $7
}

BEGIN {
    # 传感器数量,根据实际数据调整,示例中为3个
    sensor_count = 3
    # 设置输出对齐的宽度,和原始数据格式匹配
    col_width = 18
}

# 处理第一行,初始化当前时间键和传感器值存储
NR == 1 {
    current_key = get_time_key()
    for (i=8; i<=NF; i++) {
        if ($i != "NOTSAMPLED") {
            sensor_data[current_key][i-7] = $i
        }
    }
    next
}

{
    line_key = get_time_key()
    # 遇到新的时间点,先输出上一个时间点的完整数据
    if (line_key != current_key) {
        # 打印时间部分
        printf "%s", current_key
        # 遍历每个传感器,输出有效值(无有效值时用0.0补全)
        for (j=1; j<=sensor_count; j++) {
            val = (sensor_data[current_key][j] != "") ? sensor_data[current_key][j] : "0.0"
            printf "%*s", col_width, val
        }
        printf "\n"
        
        # 清理上一个时间点的数据,切换到新时间点
        delete sensor_data[current_key]
        current_key = line_key
    }
    
    # 更新当前时间点的传感器有效值
    for (i=8; i<=NF; i++) {
        if ($i != "NOTSAMPLED") {
            sensor_data[current_key][i-7] = $i
        }
    }
}

# 处理最后一个时间点的数据
END {
    printf "%s", current_key
    for (j=1; j<=sensor_count; j++) {
        val = (sensor_data[current_key][j] != "") ? sensor_data[current_key][j] : "0.0"
        printf "%*s", col_width, val
    }
    printf "\n"
}

使用方法

  1. 将上述脚本保存为process_sensor.awk
  2. 赋予执行权限:chmod +x process_sensor.awk
  3. 运行脚本处理数据:./process_sensor.awk 你的数据文件名.txt

原脚本问题说明

原脚本的问题在于:

  • 没有按时间点分组合并,而是逐行输出补全后的数据,导致每个时间点仍输出多行
  • 使用全局的filldown数组存储补全值,没有区分不同时间点,会出现跨时间点的错误补全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:15:31