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


515

行数で分割したい大きな(行数で)プレーンテキストファイルがあります。したがって、ファイルに約200万行ある場合、200k行を含む10個のファイル、または20k行を含む100個のファイルに分割します(1つのファイルと残りのファイル。均等に分割可能であることは問題ではありません)。

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


2
好奇心から、それらが「分割」された後、どのようにしてそれらを「組み合わせる」のでしょうか。「猫part2 >> part1」みたいな?または、別の忍者ユーティリティがありますか?質問を更新してもよろしいですか?
dlamotte 2010年

7
まとめると、cat part* > original
Mark Byersが2010年

9
はい猫は連結の略です。一般に、適切なコマンドは適切なコマンドを見つけるのに役立ちます。IEの出力は次の
とおりです。apropossplit

@pixelbeatかっこいいです。ありがとう
danben

3
余談ですが、OS Xユーザーは、ファイルにMAC OS X-スタイルの行末インジケーター(CR)ではなく、LINUXまたはUNIXスタイルの改行/行末インジケーター(LF)が含まれていることを確認する必要があります。改行がLineFeedではなくキャリッジリターンの場合、csplitコマンドは機能しません。Mac OSを使用している場合は、BareBonesソフトウェアのTextWranglerが役立ちます。改行文字の外観を選択できます。テキストファイルを保存するとき(または名前を付けて保存...)。

回答:


856

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メガバイトのようなファイルを作成します。


16
サイズでファイルを分割することもできます:(split -b 200m filenameメガバイトの場合はm、キロバイトの場合はk、またはバイトの場合はサフィックスなし)
Abhi Beckert

136
サイズで分割し、ファイルが改行で分割されるようにします:split -C 200m filename
Clayton Stanley

2
splitは、Unicode(UTF-16)入力で文字化けした出力を生成します。少なくとも私が持っているバージョンのWindowsでは。
めまい2013年

4
@ geotheory、TextWranglerまたはBBEditを使用してCR(Mac)の行末をLR(Linux)の行末に最初に変換することに関するスレッドの早い段階でLeberMacのアドバイスに従ってください。そのアドバイスを見つけるまで、私はあなたとまったく同じ問題を抱えていました。
ストリンガー2013

6
-dオプションはOSXでは使用できませんgsplit。代わりに使用してください。これがMacユーザーに役立つことを願っています。
user5698801 2017


39

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

georgec @ ATGIS25〜$ split -l 100000 /cygdrive/P/2012/Job_044_DM_Radio_Propogation/Working/FinalPropogation/TRC_Longlands/trc_longlands.txtを試しましたが、ディレクトリに分割ファイルがありません-出力はどこですか?
GeorgeC 2012年

1
同じディレクトリにある必要があります。例えば、私は、ファイルごとに1,000,000行によって分割次の操作を実行したい場合は:split -l 1000000 train_file train_file.と同じディレクトリに私が買ってあげるtrain_file.aa、その後、最初の100万でtrail_file.abなど、次の百万
ウィル

1
@GeorgeCを使用すると、プレフィックスがのカスタム出力ディレクトリを取得できますsplit input my/dir/
Ciro Santilli郝海东冠状病六四事件法轮功

15

使用する split

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

Syntax split [options] [INPUT [PREFIX]]

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


13

使用する:

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

ここで、1と100は、でキャプチャする行番号ですoutput.txt


これは最初の100行のみを取得します。ループして次の101..200などにファイルを連続して分割する必要があります。またはsplit、ここでのトップの回答がすべてすでに言っているように使用します。
tripleee


9

split2010年12 月22日のバージョン8.8以降のGNU coreutils から)次のパラメーターが含まれています。

-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


9

各ファイルをx行で分割したいだけの場合、与えられた答えsplitはOKです。しかし、私は誰も要件に注意を払っていないことに興味があります:

  • 「数える必要なし」-> 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

これをスクリプトに追加して、「忍者の方法」と呼ぶことができます。何もニーズに合わない場合は、ビルドすることができるからです:-)


または、単にの-nオプションを使用しますsplit
アミットNaidu

8

あなたはawkを使うこともできます

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

3
awk -v lines=200000 -v fmt="%d.txt" '{print>sprintf(fmt,1+int((NR-1)/lines))}'
Mark Edgar

0

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}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.