鉴于:一个大的文本数据文件(例如,CSV格式)用“特殊”第一线(例如,字段名)。
通缉:所述的coreutils的等效split -l
命令,但与从原始文件中的标题行出现在每个所得到的片的起点的附加要求。
我猜测的一些药汁split
和head
会做的伎俩?
鉴于:一个大的文本数据文件(例如,CSV格式)用“特殊”第一线(例如,字段名)。
通缉:所述的coreutils的等效split -l
命令,但与从原始文件中的标题行出现在每个所得到的片的起点的附加要求。
我猜测的一些药汁split
和head
会做的伎俩?
这是robhruska的剧本清理了一下:
tail -n +2 file.txt | split -l 4 - split_
for file in split_*
do
head -n 1 file.txt > tmp_file
cat "$file" >> tmp_file
mv -f tmp_file "$file"
done
我删除wc
, cut
, ls
和echo
在他们不必要的地方。 我改变了一些文件名,使他们多一点有意义的。 我打破了它在多行只以使其更易于阅读。
如果你想获得幻想,你可以使用mktemp
或tempfile
创建一个临时文件名,而不是使用硬编码的一个。
编辑
使用GNU split
有可能做到这一点:
split_filter () { { head -n 1 file.txt; cat; } > "$FILE"; }; export -f split_filter; tail -n +2 file.txt | split --lines=4 --filter=split_filter - split_
拆开进行可读性:
split_filter () { { head -n 1 file.txt; cat; } > "$FILE"; }
export -f split_filter
tail -n +2 file.txt | split --lines=4 --filter=split_filter - split_
当--filter
被指定时, split
运行用于每个输出文件的命令(在此情况下的函数,其必须导出),并将可变FILE
,在命令的环境,到文件名。
过滤器的脚本或函数可以做它想输出的内容,甚至是文件名的任何操作。 后者的一个例子可能是输出到在一个变量目录的固定文件名: > "$FILE/data.dat"
例如。
你可以在GNU的coreutils分割使用新的--filter功能> = 8.13(2011年):
tail -n +2 FILE.in |
split -l 50 - --filter='sh -c "{ head -n1 FILE.in; cat; } > $FILE"'
You can use [mg]awk:
awk 'NR==1{
header=$0;
count=1;
print header > "x_" count;
next
}
!( (NR-1) % 100){
count++;
print header > "x_" count;
}
{
print $0 > "x_" count
}' file
100 is the number of lines of each slice. It doesn't require temp files and can be put on a single line.
我是一个新手,当谈到猛砸福,但我能炮制这两个命令的怪物。 我敢肯定有更优雅的解决方案。
$> tail -n +2 file.txt | split -l 4
$> for file in `ls xa*`; do echo "`head -1 file.txt`" > tmp; cat $file >> tmp; mv -f tmp $file; done
这是假设你的输入文件file.txt
,你不使用的prefix
参数来split
,而你在不具有与启动任何其他文件的目录工作split
的默认xa*
输出格式。 另外,与你的期望分割线的尺寸更换“4”。
这会在每一个的顶部的大的csv分成999线件,与头
cat bigFile.csv | parallel --header : --pipe -N999 'cat >file_{#}.csv'
基于OLE丹的回答。 (重新奥莱的回答是:你不能使用符合pipepart计数)
这是丹尼斯·威廉姆森的剧本中一个更强大的版本。 该脚本创建了大量的临时文件,如果他们离开躺在附近,如果运行是不完整的,将是一种耻辱。 所以,让我们上路信号捕捉(见http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html然后http://tldp.org/LDP/abs/html/debugging.html )和除去我们的临时文件; 这是反正是最佳做法。
trap 'rm split_* tmp_file ; exit 13' SIGINT SIGTERM SIGQUIT
tail -n +2 file.txt | split -l 4 - split_
for file in split_*
do
head -n 1 file.txt > tmp_file
cat $file >> tmp_file
mv -f tmp_file $file
done
与任何你想要返回的代码替换“13”。 哦,你或许应该使用mktemp的反正(如某些人已经建议),所以,尽管从陷阱行RM删除“tmp_file”,更多的信号捕捉见信号手册。
我无法知道从其他人的网站直复制脚本的规则,但Geekology有一个很好的脚本,做你想要的东西,有一些意见确认其有效。 务必做到tail
-n
+2
在靠近底部的评论指出。
我很喜欢马可AWK版本,从这个简单的一行代码采纳,你,你想要可以很容易地指定分割部分粒状:
awk 'NR==1{print $0 > FILENAME ".split1"; print $0 > FILENAME ".split2";} NR>1{if (NR % 10 > 5) print $0 >> FILENAME ".split1"; else print $0 >> FILENAME ".split2"}' file
我真的很喜欢Rob和丹尼斯的版本,以至于我想改善他们。
这里是我的版本:
in_file=$1
awk '{if (NR!=1) {print}}' $in_file | split -d -a 5 -l 100000 - $in_file"_" # Get all lines except the first, split into 100,000 line chunks
for file in $in_file"_"*
do
tmp_file=$(mktemp $in_file.XXXXXX) # Create a safer temp file
head -n 1 $in_file | cat - $file > $tmp_file # Get header from main file, cat that header with split file contents to temp file
mv -f $tmp_file $file # Overwrite non-header containing file with header-containing file
done
区别:
awk
,而不是tail
由于awk
具有更好的性能 head | cat
head | cat
行,而不是两行 使用GNU并行:
parallel -a bigfile.csv --header : --pipepart 'cat > {#}'
如果你需要在每个部件的运行命令,然后GNU并行可以帮助做到这一点,太:
parallel -a bigfile.csv --header : --pipepart my_program_reading_from_stdin
parallel -a bigfile.csv --header : --pipepart --fifo my_program_reading_from_fifo {}
parallel -a bigfile.csv --header : --pipepart --cat my_program_reading_from_a_file {}
如果要分割成2份每个CPU核心(例如24个核心= 48个尺寸相等的份数):
parallel --block -2 -a bigfile.csv --header : --pipepart my_program_reading_from_stdin
如果你想分成10个MB块:
parallel --block 10M -a bigfile.csv --header : --pipepart my_program_reading_from_stdin
下面是可以用来保存CSV报头中的4衬垫(使用:头部,分割,发现,grep的,xargs的,和SED)
csvheader=`head -1 bigfile.csv` split -d -l10000 bigfile.csv smallfile_ find .|grep smallfile_ | xargs sed -i "1s/^/$csvheader\n/" sed -i '1d' smallfile_00
说明: