我有一个大的 CSV 文件,想将其分成小块。我知道我可以使用分割 CSV 文件
split -l 1000000 file.csv new
这导致零件有 1000000 行。但问题是它分裂了,但原始的也存在。由于我的磁盘空间不足,有什么方法可以在不保留原始文件的情况下分割 CSV 吗?任何帮助表示赞赏。提前致谢。
答案1
一种方法是假设 GNUstat(1)
和 GNU truncate(1)
:
#! /bin/sh
lines=1000000
size=$( wc -l "$1" | awk '{print $1}' )
tail=$(( size % lines ))
count=$(( size / lines ))
if [ $tail -ne 0 ]; then
let count++
fi
while [ $count -gt 0 ]; do
start=$(( (count - 1) * lines + 1 ))
fn=$( printf '%s_%05d' "$1" $count )
sed -n $start,\$p <"$1" >"$fn"
size_last=$( stat -c %s "$fn" )
truncate -s -$size_last "$1"
let count--
done
如果没有 GNU coreutils
,同样的事情可以在 Perl 中完成。
原始文件会在此过程中丢失,因此明智的做法是首先针对一些较小的文件测试上述内容,例如lines
设置为 100。
答案2
如果你的系统内存足够大,可以容纳整个csv
文件,你可以尝试这个非常危险将文件放入临时文件系统(即 RAM 中的虚拟硬盘驱动器),然后开始将其从那里分割到硬盘驱动器上的方法。
请注意,当 PC 断电时,文件在tmpfs
此数据将会丢失!这非常非常容易让你不开心。
通常/dev/shm
应该已经存在,仔细检查是否mount | grep shm
将 a 列为tmpfs
安装在 上/dev/shm
,然后:
mv file /dev/shm
split -l 1000000 /dev/shm/file /path/to/split/directory/
我不知道除了文件大小之外您还需要多少额外内存,因为我不熟悉 的split
内存使用情况,但我认为至少是您要分割的一百万行。
再次做好数据丢失的准备简单的停电或任何意外情况。
PS:也许您手头有一个 USB 闪存驱动器可以用作临时文件系统 - 危险性较小,但速度较慢。
答案3
如果可以颠倒 CSV 字段的顺序,您可以尝试以下操作:
SIZ=$(stat -c %s input)
tac input |\
(
IFS=""
while read -r LINE
do
ADJ=${#LINE}
SIZ=$(( (SIZ-ADJ-1) ))
truncate -s $SIZ input
echo "$LINE"
done
) |\
split -l 10 - output
与普通命令相比,它的运行时间也更长split
,但可能不会太长。
它确实节省了磁盘空间,即使启动文件占用了近 100% 的可用磁盘空间,它也能运行。
您将需要更改文件名并将-l 10
参数增加到split
.我按照我测试的方式发布了它,在一个远少于一百万行的文件上。