Bagaimana cara membagi file teks besar menjadi file yang lebih kecil dengan jumlah baris yang sama?


517

Saya punya file teks biasa (dengan jumlah baris) yang besar yang ingin saya bagi menjadi file yang lebih kecil, juga dengan jumlah baris. Jadi jika file saya memiliki sekitar 2M baris, saya ingin membaginya menjadi 10 file yang berisi 200rb baris, atau 100 file yang berisi 20rb baris (ditambah satu file dengan sisanya; secara merata dapat dibagi tidak masalah).

Saya bisa melakukan ini dengan cukup mudah di Python tapi saya bertanya-tanya apakah ada cara ninja untuk melakukan hal ini menggunakan bash dan unix utils (yang bertentangan dengan pengulangan manual dan penghitungan / garis partisi).


2
Karena penasaran, setelah mereka "berpisah", bagaimana cara seseorang "menggabungkan" mereka? Sesuatu seperti "cat part2 >> part1"? Atau ada ninja utilitas lain? keberatan memperbarui pertanyaan Anda?
dlamotte

7
Untuk menyatukannya kembali,cat part* > original
Mark Byers

9
ya kucing kependekan dari concatenate. Secara umum apropos berguna untuk menemukan perintah yang sesuai. IE melihat output dari: apropos split
pixelbeat

@pixelbeat Itu cukup keren, terima kasih
danben

3
Selain itu, pengguna OS X harus memastikan file mereka berisi LINUX atau gaya Line break / indikator End-Of-Line (LF) gaya LINUX atau UNIX, bukannya MAC OS X - indikator end-of-line (CR) gaya - perpecahan dan Perintah csplit tidak akan berfungsi jika istirahat seperti Anda adalah Pengembalian Carriage alih-alih LineFeeds. TextWrangler dari perangkat lunak BareBones dapat membantu Anda dengan ini jika Anda menggunakan Mac OS. Anda dapat memilih bagaimana Anda ingin tampilan karakter pemisah baris Anda. saat Anda menyimpan (atau Simpan Sebagai ...) file teks Anda.

Jawaban:


858

Sudahkah Anda melihat perintah 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

Anda dapat melakukan sesuatu seperti ini:

split -l 200000 filename

yang akan membuat file masing-masing dengan 200000 baris bernama xaa xab xac...

Pilihan lain, dipisah berdasarkan ukuran file keluaran (masih terbelah saat jeda baris):

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

membuat file seperti output_prefix01 output_prefix02 output_prefix03 ...masing - masing ukuran maksimal 20 megabyte.


16
Anda juga dapat membagi file berdasarkan ukuran: split -b 200m filename(m untuk megabita, k untuk kilobyte atau tanpa akhiran untuk byte)
Abhi Beckert

137
dipisah berdasarkan ukuran dan memastikan file dipisah berdasarkan jeda baris: perpecahan -C 200m nama file
Clayton Stanley

2
split menghasilkan output kacau dengan input Unicode (UTF-16). Setidaknya pada Windows dengan versi yang saya miliki.
Vertigo

4
@geotheory, pastikan untuk mengikuti saran LeberMac sebelumnya di utas tentang mengubah ujung CR (Mac) pertama menjadi akhiran LR (Linux) menggunakan TextWrangler atau BBEdit. Saya memiliki masalah yang sama persis seperti Anda sampai saya menemukan nasihat itu.
sstringer

6
-dopsi tidak tersedia di OSX, gunakan gsplitsaja. Semoga ini bermanfaat bagi pengguna Mac.
user5698801


39

Ya, ada splitperintah. Ini akan membagi file dengan garis atau byte.

$ 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.

Mencoba georgec @ ATGIS25 ~ $ split -l 100000 /cygdrive/P/2012/Job_044_DM_Radio_Propogation/Working/FinalPropogation/TRC_Longlands/trc_longlands.txt tetapi tidak ada file split di direktori -mana outputnya?
GeorgeC

1
Itu harus di direktori yang sama. Misalnya, jika saya ingin membagi 1.000.000 baris per file, lakukan hal berikut: split -l 1000000 train_file train_file.dan dalam direktori yang sama saya akan dapatkan train_file.aadengan juta pertama, kemudian trail_file.abdengan jutaan berikutnya, dll.
Will

1
@GeorgeC dan Anda bisa mendapatkan direktori output yang kustom dengan awalan: split input my/dir/.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

15

menggunakan split

Membagi file menjadi ukuran tetap, membuat file output yang berisi bagian berturut-turut dari INPUT (input standar jika tidak ada yang diberikan atau INPUT adalah `- ')

Syntax split [options] [INPUT [PREFIX]]

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


13

Menggunakan:

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

Di sini, 1 dan 100 adalah nomor baris yang akan Anda tangkap output.txt.


Ini hanya memperoleh 100 baris pertama, Anda perlu mengulanginya untuk berturut-turut membagi file menjadi 101..200 berikutnya dll. Atau hanya menggunakan splitseperti semua jawaban teratas di sini sudah memberi tahu Anda.
tripleee

10

pisahkan file "file.txt" menjadi 10.000 baris file:

split -l 10000 file.txt

9

split(dari GNU coreutils, sejak versi 8.8 dari 2010-12-22 ) termasuk parameter berikut:

-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

Dengan demikian, split -n 4 input output.akan menghasilkan empat file ( output.a{a,b,c,d}) dengan jumlah byte yang sama, tetapi garis mungkin terputus di tengah.

Jika kita ingin mempertahankan baris penuh (mis. Dibagi dengan baris), maka ini akan berhasil:

split -n l/4 input output.

Jawaban terkait: https://stackoverflow.com/a/19031247


9

Jika Anda hanya ingin membagi dengan x jumlah baris setiap file, jawaban yang diberikan splitadalah OK. Tapi, saya ingin tahu tentang tidak ada yang memperhatikan persyaratan:

  • "tanpa harus menghitungnya" -> menggunakan wc + cut
  • "Memiliki sisa dalam file tambahan" -> split tidak secara default

Saya tidak dapat melakukannya tanpa "wc + cut", tetapi saya menggunakan itu:

split -l  $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename

Ini dapat dengan mudah ditambahkan ke fungsi bashrc Anda sehingga Anda bisa memintanya lewat nama file dan potongan:

 split -l  $(expr `wc $1 | cut -d ' ' -f3` / $2) $1

Jika Anda hanya ingin x potongan tanpa sisa dalam file tambahan, cukup sesuaikan rumus untuk menjumlahkannya (potongan - 1) pada setiap file. Saya menggunakan pendekatan ini karena biasanya saya hanya ingin x jumlah file daripada x baris per file:

split -l  $(expr `wc $1 | cut -d ' ' -f3` / $2 + `expr $2 - 1`) $1

Anda dapat menambahkannya ke skrip dan menyebutnya "cara ninja", karena jika tidak ada yang sesuai dengan kebutuhan Anda, Anda dapat membuatnya :-)


Atau, cukup gunakan -nopsi split.
Amit Naidu

8

Anda juga bisa menggunakan 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 mendapatkan file kecil dan tumpah ke ukuran properti.

Metode ini akan menyebabkan jeda baris

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

Saya mencoba untuk mendapatkan dan membagi menjadi sekitar 128MB setiap file.

# 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}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.