我有一个大的(按行数)纯文本文件,我想按行数将其拆分成多个较小的文件。因此,如果我的文件大约有200万行,我想将其拆分为10个包含20万行的文件,或100个包含20k行的文件(再加上一个文件,其余部分;被平均整除并不重要)。
我可以在Python中相当容易地做到这一点,但我想知道是否有任何忍者可以使用bash和unix utils来做到这一点(与手动循环和计数/分区行相对)。
cat part* > original
我有一个大的(按行数)纯文本文件,我想按行数将其拆分成多个较小的文件。因此,如果我的文件大约有200万行,我想将其拆分为10个包含20万行的文件,或100个包含20k行的文件(再加上一个文件,其余部分;被平均整除并不重要)。
我可以在Python中相当容易地做到这一点,但我想知道是否有任何忍者可以使用bash和unix utils来做到这一点(与手动循环和计数/分区行相对)。
cat part* > original
Answers:
您看过split命令吗?
$ 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
您可以执行以下操作:
split -l 200000 filename
这将创建每个文件以200000行命名的文件xaa xab xac
...
另一个选项,按输出文件的大小拆分(仍在换行符处拆分):
split -C 20m --numeric-suffixes input_filename output_prefix
创建output_prefix01 output_prefix02 output_prefix03 ...
每个最大大小为20 MB的文件。
split -b 200m filename
(m表示兆字节,k表示千字节或字节不带后缀)
-d
该选项在OSX上不可用,请gsplit
改用。希望这对Mac用户有用。
是的,有一个split
命令。它将按行或字节分割文件。
$ 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 -l 1000000 train_file train_file.
在同一个目录下我会train_file.aa
用第一个一百万,那么trail_file.ab
下一个百万,等等
split input my/dir/
。
采用 split
将文件拆分为固定大小的片段,创建包含INPUT连续部分的输出文件(如果未指定或INPUT为'-',则为标准输入)
Syntax
split [options] [INPUT [PREFIX]]
split
(来自GNU coreutils,自2010年12月22日起为8.8版)包含以下参数:
-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
因此,split -n 4 input output.
将生成四个output.a{a,b,c,d}
具有相同字节数的文件(),但中间的行可能会中断。
如果我们要保留完整的行(即按行分割),那么这应该起作用:
split -n l/4 input output.
如果您只想按每个文件的x行数进行拆分,则给出的答案split
是可以的。但是,我很好奇没有人关注要求:
没有“ wc + cut”,我无法做到这一点,但是我正在使用:
split -l $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename
这可以很容易地添加到您的bashrc函数中,因此您可以通过传递文件名和块来调用它:
split -l $(expr `wc $1 | cut -d ' ' -f3` / $2) $1
如果只需要x个块,而没有多余的多余文件,则只需对公式进行修改,以对每个文件求和(大块-1)。我确实使用这种方法,因为通常我只希望x个文件而不是每个文件x行:
split -l $(expr `wc $1 | cut -d ' ' -f3` / $2 + `expr $2 - 1`) $1
您可以将其添加到脚本中并称为“忍者之路”,因为如果没有什么适合您的需求,则可以构建它:-)
-n
选项split
。
你也可以使用awk
awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile
awk -v lines=200000 -v fmt="%d.txt" '{print>sprintf(fmt,1+int((NR-1)/lines))}'
HDFS getmerge小文件并溢出到属性大小中。
此方法将导致换行
split -b 125m compact.file -d -a 3 compact_prefix
我尝试进行合并,并将每个文件分成大约128MB。
# 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}