How to split a large text file into smaller files with equal number of lines?
我有一个大的(按线数)纯文本文件,我想分成较小的文件,也按行数。 因此,如果我的文件有大约2M行,我想将它分成10个包含200k行的文件,或者包含20k行的100个文件(加上一个包含剩余部分的文件;均匀可分的无关紧要)。
我可以在Python中相当容易地做到这一点,但我想知道是否有任何一种使用bash和unix utils的忍者方法(而不是手动循环和计数/分区行)。
你看过split命令了吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ split --help Usage: split [OPTION] [INPUT [PREFIX]] Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default size is 1000 lines, and default PREFIX is `x'. With no INPUT, or when INPUT is -, read standard input. Mandatory arguments to long options are mandatory for short options too. -a, --suffix-length=N use suffixes of length N (default 2) -b, --bytes=SIZE put SIZE bytes per output file -C, --line-bytes=SIZE put at most SIZE bytes of lines per output file -d, --numeric-suffixes use numeric suffixes instead of alphabetic -l, --lines=NUMBER put NUMBER lines per output file --verbose print a diagnostic to standard error just before each output file is opened --help display this help and exit --version output version information and exit |
你可以这样做:
1 | split -l 200000 filename |
这将创建每个名为
另一个选项,按输出文件的大小分割(仍然在换行符上拆分):
1 | split -C 20m --numeric-suffixes input_filename output_prefix |
创建文件,如
拆分命令怎么样?
1 | split -l 200000 mybigfile.txt |
是的,有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | $ split --help Usage: split [OPTION]... [INPUT [PREFIX]] Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default size is 1000 lines, and default PREFIX is `x'. With no INPUT, or when INPUT is -, read standard input. Mandatory arguments to long options are mandatory for short options too. -a, --suffix-length=N use suffixes of length N (default 2) -b, --bytes=SIZE put SIZE bytes per output file -C, --line-bytes=SIZE put at most SIZE bytes of lines per output file -d, --numeric-suffixes use numeric suffixes instead of alphabetic -l, --lines=NUMBER put NUMBER lines per output file --verbose print a diagnostic just before each output file is opened --help display this help and exit --version output version information and exit SIZE may have a multiplier suffix: b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024, GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y. |
使用
Split a file into fixed-size pieces, creates output files containing consecutive sections of INPUT (standard input if none is given or INPUT is `-')
split [options] [INPUT [PREFIX]]
http://ss64.com/bash/split.html
使用:
1 | sed -n '1,100p' filename > output.txt |
这里,1和100是您将在
将文件"file.txt"拆分为10000行文件:
1 | split -l 10000 file.txt |
1 2 3 4 5 6 7 8 9 | -n, --number=CHUNKS generate CHUNKS output files; see explanation below CHUNKS may be: N split into N files based on size of input K/N output Kth of N to stdout l/N split into N files without splitting lines/records l/K/N output Kth of N to stdout without splitting lines/records r/N like 'l' but use round robin distribution r/K/N likewise but only output Kth of N to stdout |
因此,
如果我们想保留整行(即按行分割),那么这应该有效:
1 | split -n l/4 input output. |
相关回答:https://stackoverflow.com/a/19031247
如果您只想将每个文件的x行分开,那么关于
- "无需计算" - >使用wc + cut
- "将剩余部分放在额外的文件中" - >拆分默认情况下
没有"wc + cut",我不能那样做,但我正在使用它:
1 | split -l $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename |
这可以很容易地添加到你的bashrc函数中,这样你就可以调用它来传递文件名和块:
1 | split -l $(expr `wc $1 | cut -d ' ' -f3` / $2) $1 |
如果您只想在额外文件中使用没有余数的x块,只需调整公式以对每个文件求和(块 - 1)。我确实使用这种方法,因为通常我只需要x个文件而不是每个文件x行:
1 | split -l $(expr `wc $1 | cut -d ' ' -f3` / $2 + `expr $2 - 1`) $1 |
您可以将其添加到脚本中并将其称为"忍者方式",因为如果没有满足您的需求,您可以构建它:-)
你也可以使用awk
1 | awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile |
HDFS getmerge小文件并溢出到属性大小。
此方法将导致换行
1 | split -b 125m compact.file -d -a 3 compact_prefix |
我尝试getmerge并分成每个文件大约128MB。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # split into 128m ,judge sizeunit is M or G ,please test before use. begainsize=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $1}' ` sizeunit=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $2}' ` if [ $sizeunit ="G" ];then res=$(printf"%.f" `echo"scale=5;$begainsize*8"|bc`) else res=$(printf"%.f" `echo"scale=5;$begainsize/128"|bc`) # celling ref http://blog.csdn.net/naiveloafer/article/details/8783518 fi echo $res # split into $res files with number suffix. ref http://blog.csdn.net/microzone/article/details/52839598 compact_file_name=$compact_file"_" echo"compact_file_name :"$compact_file_name split -n l/$res $basedir/$compact_file -d -a 3 $basedir/${compact_file_name} |