Wie teile ich eine große Textdatei in kleinere Dateien mit der gleichen Anzahl von Zeilen auf?

515

Ich habe eine große (nach Anzahl der Zeilen) Nur-Text-Datei, die ich in kleinere Dateien aufteilen möchte, auch nach Anzahl der Zeilen. Wenn meine Datei ungefähr 2 Millionen Zeilen enthält, möchte ich sie in 10 Dateien mit 200.000 Zeilen oder 100 Dateien mit 20.000 Zeilen aufteilen (plus eine Datei mit dem Rest; gleichmäßig teilbar zu sein spielt keine Rolle).

Ich könnte dies in Python ziemlich einfach tun, aber ich frage mich, ob es irgendeine Ninja-Möglichkeit gibt, dies mit Bash- und Unix-Utils zu tun (im Gegensatz zum manuellen Schleifen und Zählen / Partitionieren von Zeilen).

danben
quelle
2
Wie "kombiniert" man sie aus Neugier, nachdem sie "gespalten" sind? So etwas wie "Katze Teil2 >> Teil1"? Oder gibt es ein anderes Ninja-Dienstprogramm? Möchten Sie Ihre Frage aktualisieren?
Dlamotte
7
Um es wieder zusammenzusetzen,cat part* > original
Mark Byers
9
Ja, Katze ist die Abkürzung für verketten. Im Allgemeinen ist apropos nützlich, um geeignete Befehle zu finden. IE sehen die Ausgabe von: apropos split
pixelbeat
@ Pixelbeat Das ist ziemlich cool, danke
Danben
3
Nebenbei sollten OS X-Benutzer sicherstellen, dass ihre Datei Zeilenumbrüche / Zeilenendeindikatoren (LF) im LINUX- oder UNIX-Stil anstelle von MAC OS X - Zeilenende-Indikatoren (CR) - Split und enthält csplit-Befehle funktionieren nicht, wenn Ihre ähnlichen Unterbrechungen Carriage Returns anstelle von LineFeeds sind. TextWrangler von der BareBones-Software kann Ihnen dabei helfen, wenn Sie unter Mac OS arbeiten. Sie können auswählen, wie Ihre Zeilenumbruchzeichen aussehen sollen. wenn Sie Ihre Textdateien speichern (oder speichern unter ...).

Antworten:

856

Haben Sie sich den Befehl split angesehen?

$ 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

Sie könnten so etwas tun:

split -l 200000 filename

Dadurch werden Dateien mit jeweils 200000 Zeilen mit dem Namen xaa xab xac... erstellt.

Eine weitere Option, aufgeteilt nach der Größe der Ausgabedatei (wird immer noch bei Zeilenumbrüchen aufgeteilt):

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

Erstellt Dateien mit output_prefix01 output_prefix02 output_prefix03 ...einer maximalen Größe von 20 Megabyte.

Mark Byers
quelle
16
Sie können eine Datei auch nach Größe aufteilen: split -b 200m filename(m für Megabyte, k für Kilobyte oder kein Suffix für Bytes)
Abhi Beckert
136
Teilen Sie nach Größe und stellen Sie sicher, dass die Dateien bei Zeilenumbrüchen aufgeteilt werden: split -C 200m Dateiname
Clayton Stanley
2
split erzeugt eine verstümmelte Ausgabe mit Unicode-Eingang (UTF-16). Zumindest unter Windows mit der Version, die ich habe.
Schwindel
4
@geotheory, befolgen Sie unbedingt die Ratschläge von LeberMac weiter oben im Thread zum ersten Konvertieren von CR (Mac) -Leitungsenden in LR (Linux) -Leitungsenden mit TextWrangler oder BBEdit. Ich hatte genau das gleiche Problem wie Sie, bis ich diesen Rat gefunden habe.
Sstringer
6
-dOption ist unter OSX nicht verfügbar, verwenden Sie gsplitstattdessen. Hoffe, dies ist nützlich für Mac-Benutzer.
user5698801
80

Wie wäre es mit dem Befehl split ?

split -l 200000 mybigfile.txt
Robert Christie
quelle
39

Ja, es gibt einen splitBefehl. Eine Datei wird nach Zeilen oder Bytes aufgeteilt.

$ 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.
Dave Kirby
quelle
Versucht georgec @ ATGIS25 ~ $ split -l 100000 /cygdrive/P/2012/Job_044_DM_Radio_Propogation/Working/FinalPropogation/TRC_Longlands/trc_longlands.txt, aber es gibt keine geteilten Dateien im Verzeichnis - wo ist die Ausgabe?
GeorgeC
1
Es sollte sich im selben Verzeichnis befinden. Wenn ich beispielsweise durch 1.000.000 Zeilen pro Datei teilen möchte, gehen Sie wie folgt vor: split -l 1000000 train_file train_file.und im selben Verzeichnis erhalte ich train_file.aadie erste Million, dann trail_file.abdie nächste Million usw.
Wird
1
@GeorgeC und Sie können benutzerdefinierte Ausgabeverzeichnisse mit dem Präfix erhalten : split input my/dir/.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
15

verwenden split

Teilen Sie eine Datei in Teile mit fester Größe, erstellen Sie Ausgabedateien mit aufeinanderfolgenden Abschnitten von INPUT (Standardeingabe, wenn keine angegeben ist oder INPUT "-" ist).

Syntax split [options] [INPUT [PREFIX]]

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

zmbush
quelle
13

Verwenden:

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

Hier sind 1 und 100 die Zeilennummern, in denen Sie erfassen werden output.txt.

Harshwardhan
quelle
Dadurch werden nur die ersten 100 Zeilen erhalten. Sie müssen sie schleifen, um die Datei nacheinander in die nächsten 101..200 usw. aufzuteilen. Oder verwenden Sie einfach, splitwie alle Top-Antworten hier bereits sagen.
Tripleee
10

Teilen Sie die Datei "file.txt" in Dateien mit 10000 Zeilen auf:

split -l 10000 file.txt
ialqwaiz
quelle
9

split(von GNU coreutils, seit Version 8.8 vom 22.12.2010 ) enthält den folgenden Parameter:

-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

Somit split -n 4 input output.werden vier Dateien ( output.a{a,b,c,d}) mit der gleichen Anzahl von Bytes generiert , aber die Zeilen können in der Mitte unterbrochen sein.

Wenn wir vollständige Zeilen beibehalten möchten (dh durch Zeilen geteilt), sollte dies funktionieren:

split -n l/4 input output.

Verwandte Antwort: https://stackoverflow.com/a/19031247

Denilson Sá Maia
quelle
9

Wenn Sie jede Datei nur durch x Zeilen teilen möchten, sind die angegebenen Antworten splitin Ordnung. Aber ich bin neugierig, dass niemand auf Anforderungen geachtet hat:

  • "ohne sie zählen zu müssen" -> mit wc + cut
  • "den Rest in einer zusätzlichen Datei haben" -> split funktioniert standardmäßig

Ich kann das nicht ohne "wc + cut" machen, aber ich benutze das:

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

Dies kann einfach zu Ihren bashrc-Funktionen hinzugefügt werden, sodass Sie es einfach über Dateinamen und Chunks aufrufen können:

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

Wenn Sie nur x Chunks ohne Rest in einer zusätzlichen Datei möchten, passen Sie die Formel einfach an, um sie (Chunks - 1) für jede Datei zu summieren. Ich benutze diesen Ansatz, weil ich normalerweise nur x Anzahl von Dateien anstelle von x Zeilen pro Datei möchte:

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

Sie können das einem Skript hinzufügen und es Ihren "Ninja-Weg" nennen, denn wenn nichts Ihren Anforderungen entspricht, können Sie es erstellen :-)

m3nda
quelle
Oder nutzen Sie einfach die -nOption von split.
Amit Naidu
8

Sie können auch awk verwenden

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

HDFS getmerge kleine Datei und verschüttet in Eigenschaftsgröße.

Diese Methode führt zu Zeilenumbrüchen

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

Ich versuche, jede Datei in ungefähr 128 MB aufzuteilen.

# 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}
Matiji66
quelle