Verwandte, aber keine zufriedenstellenden Antworten: Wie kann ich eine große Textdatei in Abschnitte mit etwa 500 Wörtern aufteilen?
Ich versuche, eine Textdatei ( http://mattmahoney.net/dc/text8.zip ) mit> 10 ^ 7 Wörtern in einer Zeile zu erstellen und in Zeilen mit jeweils N Wörtern aufzuteilen. Mein aktueller Ansatz funktioniert, ist aber ziemlich langsam und hässlich (unter Verwendung eines Shell-Skripts):
i=0
for word in $(sed -e 's/\s\+/\n/g' input.txt)
do
echo -n "${word} " > output.txt
let "i=i+1"
if [ "$i" -eq "1000" ]
then
echo > output.txt
let "i=0"
fi
done
Irgendwelche Tipps, wie ich das schneller oder kompakter machen kann?
text-processing
sed
awk
split
Cory Schillaci
quelle
quelle
Antworten:
Angenommen, Ihre Wortdefinition ist eine Folge von nicht leeren Zeichen, die durch Leerzeichen getrennt sind. Hier ist eine
awk
Lösung für Ihre einzeilige Dateiquelle
Verwendung
xargs
(17 Sekunden):Es verwendet das
-n
Flagxargs
, dessen maximale Anzahl von Argumenten definiert wird. Wechseln Sie einfach1000
zu500
oder was auch immer Sie wollen.Ich habe eine Testdatei mit 10 ^ 7 Wörtern erstellt:
Hier sind die Zeitstatistiken:
quelle
xargs
dem Zitat-Stripping-Verhaltenn
desto langsamer wird es, nur damit Sie es wissen. Mit habe-n10
ich es nach ca. 8 Minuten Wartezeit abgesagt ...Perl scheint erstaunlich gut darin zu sein:
Erstellen Sie eine Datei mit 10.000.000 durch Leerzeichen getrennten Wörtern
Perl fügt jetzt nach jeweils 1.000 Wörtern eine neue Zeile hinzu
Zeitliche Koordinierung
Ergebnisse überprüfen
Die akzeptierte awk-Lösung hat in meiner Eingabedatei etwas mehr als 5 Sekunden gedauert.
quelle
Nicht wirklich geeignet, wenn die
N
Anzahl der Wörter eine große Zahl ist, aber wenn es sich um eine kleine Zahl handelt (und im Idealfall keine führenden / nachfolgenden Leerzeichen in Ihrer einzeiligen Datei), sollte dies ziemlich schnell sein (z. B. 5 Wörter pro Zeile):quelle
paste
Zeichenfolge im laufenden Betrieb. Zum Beispiel:tr -s '[[:blank:]]' '\n' < text8 | paste -d' ' $(perl -le 'print "- " x 1000')
set
etc ... und selbst dann gibt es eine systemspezifische maximale Anzahl von Argumenten (ich bin nicht mit allen Varianten vonpaste
aber vertraut Ich denke, bei einigen Implementierungen gibt es GrenzenDer gleiche sed-Befehl kann vereinfacht werden, indem Sie angeben, mit wie vielen Wortraummustern Sie übereinstimmen möchten. Ich hatte keine großen String-Dateien zum Testen, aber ohne die Schleifen in Ihrem ursprünglichen Skript sollte dies so schnell ausgeführt werden, wie Ihr Prozessor die Daten streamen kann. Zusätzlicher Vorteil, es funktioniert genauso gut bei mehrzeiligen Dateien.
quelle
Der ehrwürdige
fmt(1)
Befehl kann, obwohl er nicht streng mit "einer bestimmten Anzahl von Wörtern" arbeitet, ziemlich schnell lange Zeilen auf eine bestimmte Zielbreite (oder maximale Breite) umbrechen:Oder mit modernem Perl für eine bestimmte Anzahl von Wörtern, z. B. 10, und unter der Annahme eines einzelnen Leerzeichens als Wortgrenze:
quelle
Der
pr
Befehl coreutils ist ein weiterer Kandidat: Die einzige Falte scheint darin zu bestehen, dass die Seitenbreite so groß sein muss, dass sie der Ausgabebreite entspricht.Verwenden einer Datei, die mit dem 10.000.000-Wortgenerator von @ Glenn_Jackman erstellt wurde.
wobei die Zählungen wie folgt bestätigt werden
[Glenns Perl-Lösung ist immer noch etwas schneller, ~ 1,8 Sekunden auf diesem Computer].
quelle
in Go würde ich es so versuchen
quelle