web-dev-qa-db-ja.com

大きなテキストファイルを同じ行数の小さなファイルに分割する方法

私は、行数で、もっと小さなファイルに分割したい、大きな(行数による)プレーンテキストファイルを持っています。だから私のファイルが約200万行ある場合、私はそれを200k行を含む10個のファイル、または20k行を含む100個のファイルに分割したいと思います。

私はPythonでこれをかなり簡単に行うことができましたが、bashとunix utilsを使ってこれを行うための何らかの忍者方法があるのではないかと思っています(手動でループして数える/分割するのとは対照的に)。

428
danben

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

これは、それぞれxaa xab xacという名前の200000行のファイルを作成します。

もう1つのオプションは、出力ファイルのサイズで分割する(それでも改行時に分割する):

 split -C 20m --numeric-suffixes input_filename output_prefix

それぞれ最大サイズ20メガバイトのoutput_prefix01 output_prefix02 output_prefix03 ...のようなファイルを作成します。

739
Mark Byers

split コマンドはどうですか。

split -l 200000 mybigfile.txt
73
Robert Christie

はい、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.
36
Dave Kirby

splitを使う

ファイルを固定サイズの断片に分割し、INPUTの連続したセクションを含む出力ファイルを作成します(何も指定されていない場合、またはINPUTが ` - 'の場合は標準入力)

Syntax split [options] [INPUT [PREFIX]]

http://ss64.com/bash/split.html

13
zmbush

つかいます:

sed -n '1,100p' filename > output.txt

ここで、1と100はoutput.txtに取り込む行番号です。

13
Harshwardhan

ファイル "file.txt"を10000行のファイルに分割します。

split -l 10000 file.txt
9
ialqwaiz

awkも使えます

awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile
8
ghostdog74

各ファイルをx行で分割したいだけの場合は、splitに関する回答は問題ありません。しかし、私は誰もが要件に注意を払わなかったことに興味があります。

  • "それらを数える必要なしに" - > wc + cutを使う
  • 「余ったファイルに余りがある」 - > 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

これをスクリプトに追加して、それをあなたの「忍者の方法」と呼ぶことができます。あなたのニーズを満たすものがなければ、それを構築することができます:-)

6
erm3nda

split(from 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.は同じバイト数で4つのファイル(output.a{a,b,c,d})を生成しますが、途中で行が途切れる可能性があります。

フルラインを維持したい(つまり、ラインで分割する)場合は、これでうまくいくはずです。

split -n l/4 input output.

関連回答: https://stackoverflow.com/a/19031247

5

HDFSは小さなファイルを取得し、プロパティサイズにこぼしました。

このメソッドは改行を引き起こします

split -b 125m compact.file -d -a 3 compact_prefix

私はgetmergeして、ファイルごとに約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}
0
Matiji66