【问题标题】:splitting a CSV and keeping the header without intermediate files拆分 CSV 并保留没有中间文件的标题
【发布时间】:2014-11-03 05:05:08
【问题描述】:

我正在尝试将十几个 100MB 以上的 csv 文件拆分为可管理的较小文件以用于 curl 帖子。

我已经设法做到了,但是有很多临时文件和 IO。这需要永恒。

我希望有人能告诉我一种更有效地做到这一点的方法;最好几乎没有磁盘 io #!/bin/sh

for csv in $(ls *.csv); do
    tail -n +2 $csv | split -a 5 -l - $RANDOM.split.
done

# chose a file randomly to fetch the header from   

header=$(ls *.csv |sort -R |tail -1 | cut -d',' -f1)

mkdir split

for x in $(/usr/bin/find . -maxdepth 1 -type f -name '*.split.*'); do
    echo Processing $x
    cat header $x >> split/$x
    rm -f $x
done

上述脚本可能无法完全运行。我基本上是通过这些命令的组合来完成它的。

我决定在上传失败的情况下完全使 curl POST 另一个步骤;如果全部发布,我不想丢失数据。但是,如果 curl 出错,可以将数据放入重做文件夹中,那么它可以工作。

#!/bin/sh

# working on a progress indicator as a percentage. Never finished.
count=$(ls -1 | wc -l 2> /dev/null | cut -d' ' -f1)

for file in $(/usr/bin/find . -maxdepth 1 -type f); do
    echo Processing $file
    curl -XPOST --data-binary @$file -H "Content-Type: text/cms+csv" $1
done

编辑 1 -- 为什么是 RANDOM?因为 split 在拆分下一个文件时会产生与第一个文件完全相同的文件。所以 .. aa ab ac ... 将为每个文件生成。我需要确保 split 生成的每个文件在整个运行过程中都是唯一的

【问题讨论】:

  • 您总是需要 I/O 从现有文件写入文件的新版本。使该过程尽可能高效应该是您的重点。照原样,您的问题中有太多“其他”内容。 (为什么是 $RANDOM,这真的是您解决方案的要求,还是您正在试验。其他事情也不清楚)。可能包括输入文件结构的 ascii 艺术,然后是这些输入预期的输出文件。 (只是一个小样本集)。祝你好运。
  • split 在拆分时总是会产生相同的文件。我需要随机确保每个文件拆分都会产生唯一的拆分文件
  • 对我来说已经很晚了,我无法从你的口头描述中想象出你想要做什么,但我相信其他人很快就会提出可行的解决方案。祝你好运!
  • 此问题已在 Unix.SE 交叉发布:unix.stackexchange.com/questions/165632/…

标签: bash csv curl cat tail


【解决方案1】:

不太确定您想要完成什么,但在我看来您正在逐行处理。因此,如果您序列化所有 csv 文件和行,则无需磁盘 I/O 即可完成。但是根据您的描述,我无法判断此脚本是运行多个实例还是仅运行一个实例(多个进程或一个进程)。因此,我可以尽力模仿您的脚本以达到尽可能相似的结果,但要解决磁盘 I/O 问题。下面提供了代码,但如果有脚本错误,请更正,因为我无法运行/调试/验证它:

for csv in $(ls *.csv | sort -R); do
    # first read line skip the first line, since I see your tail -n +2 command.
    (read line;
     count=0;
     while read line; do
         Processing $line;
         count=$(($count + 1));
         echo $csv.$count >> split/$count;
     done
    ) < $csv
done

您的“处理”代码现在应该从详细行而不是文件进行处理。也许一个管道并让你的Processing 在 STDIN 上处理就可以了:

echo $line | Processing

您的 curl 可以执行类似的方式,从 STDIN 进行处理,通过将 @$file 替换为 -,您可以打印您希望 curl 发送的内容,然后将其通过管道传递给 curl,类似于以下内容:

ProcessingAndPrint | curl -XPOST --data-binary - -H "Content-Type: text/cms+csv" $1

【讨论】:

  • 我没有看到 $csv 的拆分位置。
  • 在您的拆分中,您使用-1,为每个拆分文件仅拆分一行,即逐行拆分。等效地,我使用 while 循环 + 读取 + I/O 重定向,即“
猜你喜欢
  • 1970-01-01
  • 2016-09-20
  • 2019-11-24
  • 2018-12-27
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
相关资源
最近更新 更多