it-swarm.com.de

Wie teilt man eine große Textdatei in kleinere Dateien mit gleicher Zeilenanzahl auf?

Ich habe eine große (nach Zeilenanzahl) Nur-Text-Datei, die ich in kleinere Dateien aufteilen möchte, auch nach Zeilenanzahl. Wenn meine Datei etwa 2 Millionen Zeilen lang ist, möchte ich sie in 10 Dateien aufteilen, die 200.000 Zeilen enthalten, oder 100 Dateien, die 20.000 Zeilen enthalten (plus eine Datei mit dem Rest; es ist egal, ob sie gleichmäßig teilbar ist).

Ich könnte das ziemlich leicht in Python machen, aber ich frage mich, ob es eine Art Ninja-Methode gibt, um dies mit Bash und Unix-Utils zu tun (im Gegensatz zum manuellen Schleifen und Zählen/Partitionieren von Zeilen).

410
danben

Haben Sie sich den Split-Befehl 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 andere Option, aufgeschlüsselt nach Größe der Ausgabedatei (teilt sich immer noch bei Zeilenumbrüchen):

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

erstellt Dateien wie output_prefix01 output_prefix02 output_prefix03 ... mit einer maximalen Größe von 20 MB.

712
Mark Byers

Wie wäre es mit dem Befehl split ?

split -l 200000 mybigfile.txt
69
Robert Christie

Ja, es gibt einen split Befehl. Es wird eine Datei in 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.
34
Dave Kirby

verwenden Sie split

Eine Datei in Stücke mit fester Größe aufteilen, erstellt Ausgabedateien, die aufeinanderfolgende Abschnitte von INPUT enthalten (Standardeingabe, wenn keine angegeben ist oder INPUT "-" ist).

Syntax split [options] [INPUT [PREFIX]]

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

13
zmbush

Benutzen:

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

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

12
Harshwardhan

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

split -l 10000 file.txt
9
ialqwaiz

sie können auch awk verwenden

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

Falls Sie nur eine x-Zeilenanzahl pro Datei aufteilen möchten, sind die Antworten zu split in Ordnung. Aber ich bin neugierig, dass niemand die Anforderungen beachtet hat:

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

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

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

Dies kann einfach zu Ihren bashrc-Funktionen hinzugefügt werden, so dass Sie es einfach mit 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 wünschen, passen Sie die Formel einfach an, um sie in jeder Datei zu summieren (Chunks - 1). Ich verwende diesen Ansatz, weil ich normalerweise nur x Anzahl der Dateien und nicht x Zeilen pro Datei benötige:

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

Sie können das zu einem Skript hinzufügen und es als "Ninja-Methode" bezeichnen, denn wenn nichts Ihren Anforderungen entspricht, können Sie es bauen :-)

6
erm3nda

split (von GNU coreutils, seit Version 8.8 vom 2010-12-22 ) 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

Daher generiert split -n 4 input output. vier Dateien (output.a{a,b,c,d}) mit der gleichen Anzahl von Bytes, in der Mitte sind jedoch Zeilen unterbrochen.

Wenn wir vollständige Zeilen beibehalten möchten (d. H. Durch Zeilen aufteilen), sollte dies funktionieren:

split -n l/4 input output.

Zugehörige Antwort: https://stackoverflow.com/a/19031247

4

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

Diese Methode führt zu einem Zeilenumbruch 

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

Ich versuche, mich in etwa 128 MB jeder Datei zusammenzuschneiden.

# 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