【问题标题】:concantenate csv files by column and include timestamp from file name按列连接 csv 文件并包含文件名中的时间戳
【发布时间】:2019-03-15 17:31:17
【问题描述】:

我想加入 500 个 csv 文件

我先解释一下 csv 格式,每个 csv 文件都命名为 log-yyyy-mm-dd.hh:mm:ss.csv

其结构没有列标题

eventID,number

例如

FLAGS-2,16
DOOR6-234,800

我想像这样格式化这些数据

eventID,filename,filename,filename  ---and so on for the 500+ files

eventID,log-2019-03-10.21:00:01.csv,log-2019-03-15.12:00:01.csv
FLAGS-2,16,54
FLAGS-3,16,9

我首先考虑使用 bash 和 awk 来做这件事,但当我发现偶尔如果数据没有记录在文件中时,我就放弃了。它不存储该 eventID 的数字

当我做find . -name '*.csv' | xargs wc -l

有些文件有 7803 行有些有 7800 等等

所以在一个文件中我可以有以下内容

FLAGS-2,16
FLAGS-3,19
FLAGS-4,02

还有下一个

FLAGS-2,16
FLAGS-4,02

下一个最好的方法是什么

谢谢

【问题讨论】:

  • 您真的想在Bash 中执行此操作吗?我会推荐像 Python 这样的脚本语言
  • 可以使用join 加入文件,但我建议不要这样做,因为join 一次只能处理两个文件。您必须拨打join 500 次。 awk 脚本应该相对较快地完成任务。
  • 环境有限,它只是一个路由器,路由器需要在周末将日志放在一起并通过smtp发送数据。我无法安装python

标签: bash csv


【解决方案1】:

这是一个 bash/awk 解决方案,尽管它不是最有效的方法。但它足够清晰,易于理解和维护。

基本上,它首先创建标题行和joined.csv 文件。然后有一个循环用于查找所有 csv 文件中的所有唯一 ID。然后在每个 csv 文件中查找每个 key,将值附加到 line。然后最后将每个line 附加到生成的joined.csv 文件中。

#!/bin/bash

header=eventID
for csv_file in $( ls -1 log*csv)
do
    header="$header,$csv_file"
done
echo $header > joined.csv

for key in $( awk -F, '{print $1}' log*csv | sort -u )
do
    line=$key
    for csv_file in $( ls -1 log*csv)
    do
        value=$( grep $key $csv_file | awk -F, '{print $2}' )
        line="$line,$value"
    done
    echo $line >> joined.csv
done

希望这会有所帮助!

【讨论】:

  • 哇并没有期待完整的解决方案,我不得不在其中添加一个 sed 来处理 windows eol,但我的解释错误我从未想过日志会在 linux 机器上包含 windows eols。但我可以看到它是多么的低效肯定有一种更好的方法可以将变量写入特定列,就像 pandas 在 python 中所做的那样
  • ls 中的 -1 是必需的吗?我一直认为在脚本中使用 ls 时默认为 -1 和 -1 只是为了让用户可以直观地看到它。我可能是错的,但如果你不问你就不会学习:)
  • 嗨,我认为您对 -1 的看法是正确的。老实说,我不知道为什么。也许 ls 在交互模式下的工作方式不同,或者 bash 解释器分隔新行和制表符?可能是另一个问题... :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-13
  • 1970-01-01
  • 1970-01-01
  • 2020-05-27
  • 2015-12-11
  • 2021-08-14
  • 2018-05-24
相关资源
最近更新 更多