Ich habe ein bisschen Probleme beim Aufteilen einer großen Textdatei in mehrere kleinere. Die Syntax meiner Textdatei lautet wie folgt:
dasdas #42319 blaablaa 50 50
content content
more content
content conclusion
asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion
asdasd #299 yadayada 60 40
content
content
contend done
...and so on
(dasdas # 42319 blaablaa 50 50, content content, more content & content schlussfolgerung sind alle ihre eigenen separaten zeilen, gefolgt von einer leeren zeile am ende dieser informationstabelle. eine typische informationstabelle in meiner datei hat irgendwo zwischen 10-40 zeilen. )
Ich würde diese Datei in n kleinere Dateien aufteilen, wobei n die Menge der Inhaltstabellen ist.
Das ist
dasdas #42319 blaablaa 50 50
content content
more content
content conclusion
wäre eine eigene separate Datei (whateverN.txt)
und
asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion
nochmal eine separate datei whateverN + 1.txt und so weiter.
Es scheint, als ob awk
oder Perl
ein geschicktes Werkzeug dafür sind, aber sie noch nie zuvor verwendet zu haben, ist irgendwie verwirrend.
Ich habe diese beiden Fragen gefunden, die fast meinem Problem entsprechen, konnte aber die Syntax nicht an meine Bedürfnisse anpassen.
Textdatei in mehrere Dateien aufteilen &
https://unix.stackexchange.com/questions/46325/how-can-i-split-a-text-file-into-multiple-text-files
Wie soll man die Kommandozeilen-Eingaben ändern, damit es mein Problem löst?
Wenn Sie RS
auf null setzen, wird awk angewiesen, eine oder mehrere Leerzeilen als Datensatztrennzeichen zu verwenden. Dann können Sie einfach NR
verwenden, um den Namen der Datei festzulegen, die jedem neuen Datensatz entspricht:
awk -v RS= '{print > ("whatever-" NR ".txt")}' file.txt
RS: Dies ist awks Input Record Separator. Der Standardwert ist eine Zeichenfolge, die ein einzelnes Zeilenumbruchzeichen enthält. Dies bedeutet, dass ein Eingabedatensatz aus einer einzelnen Textzeile besteht. Dies kann auch die Nullzeichenfolge sein. In diesem Fall werden Datensätze durch Leerzeilen getrennt. oder ein regulärer Ausdruck. In diesem Fall werden Datensätze durch Übereinstimmungen mit dem regulären Ausdruck im Eingabetext getrennt.
$ cat file.txt
dasdas #42319 blaablaa 50 50
content content
more content
content conclusion
asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion
asdasd #299 yadayada 60 40
content
content
contend done
$ awk -v RS= '{print > ("whatever-" NR ".txt")}' file.txt
$ ls whatever-*.txt
whatever-1.txt whatever-2.txt whatever-3.txt
$ cat whatever-1.txt
dasdas #42319 blaablaa 50 50
content content
more content
content conclusion
$ cat whatever-2.txt
asdasd #92012 blaablaa 30 70
content again
more of it
content conclusion
$ cat whatever-3.txt
asdasd #299 yadayada 60 40
content
content
contend done
$
Perl hat eine nützliche Funktion, die als Trennzeichen für Eingabedatensätze bezeichnet wird. $/
.
Dies ist die Markierung zum Trennen von Datensätzen beim Lesen einer Datei.
So:
#!/usr/bin/env Perl
use strict;
use warnings;
local $/ = "\n\n";
my $count = 0;
while ( my $chunk = <> ) {
open ( my $output, '>', "filename_".$count++ ) or die $!;
print {$output} $chunk;
close ( $output );
}
Genau so. Der <>
ist insofern das 'magische' Dateihandle, als er weitergeleitete Daten oder Dateien liest, die in der Befehlszeile angegeben sind (öffnet und liest sie). Dies ähnelt der Funktionsweise von sed
oder grep
.
Dies kann zu einem Einzeiler reduziert werden:
Perl -00 -pe 'open ( $out, '>', "filename_".++$n ); select $out;' yourfilename_here
Sie können diese awk
verwenden,
awk 'BEGIN{file="content"++i".txt"} !NF{file="content"++i".txt";next} {print > file}' yourfile
(ODER)
awk 'BEGIN{i++} !NF{++i;next} {print > "filename"i".txt"}' yourfile
Mehr lesbares Format:
BEGIN {
file="content"++i".txt"
}
!NF {
file="content"++i".txt";
next
}
{
print > file
}
Falls Sie die Fehlermeldung "zu viele offene Dateien" erhalten, gehen Sie wie folgt vor ...
awk: whatever-18.txt makes too many open files
input record number 18, file file.txt
source line number 1
Möglicherweise müssen Sie die neu erstellte Datei wie folgt schließen, bevor Sie eine neue erstellen können.
awk -v RS= '{close("whatever-" i ".txt"); i++}{print > ("whatever-" i ".txt")}' file.txt
Da es Freitag ist und ich mich ein bisschen hilfsbereit fühle ... :)
Versuche dies. Wenn die Datei so klein ist, wie Sie meinen, ist es am einfachsten, sie alle auf einmal zu lesen und im Speicher zu arbeiten.
use strict;
use warnings;
# Slurp file
local $/ = undef;
open my $fh, '<', 'test.txt' or die $!;
my $text = <$fh>;
close $fh;
# split on double new line
my @chunks = split(/\n\n/, $text);
# make new files from chunks
my $count = 1;
for my $chunk (@chunks) {
open my $ofh, '>', "whatever$count.txt" or die $!;
print $ofh $chunk, "\n";
close $ofh;
$count++;
}
In den Perl
-Dokumenten können einzelne Befehle erläutert werden, die Sie nicht verstehen. An dieser Stelle sollten Sie sich jedoch wahrscheinlich auch ein Tutorial ansehen.
Versuchen Sie auch dieses Bash-Skript
#!/bin/bash
i=1
fileName="OutputFile_$i"
while read line ; do
if [ "$line" == "" ] ; then
((++i))
fileName="OutputFile_$i"
else
echo $line >> "$fileName"
fi
done < InputFile.txt
awk -v RS="\n\n" '{for (i=1;i<=NR;i++); print > i-1}' file.txt
Legt das Datensatztrennzeichen als Leerzeile fest und druckt jeden Datensatz als separate Datei mit den Nummern 1, 2, 3 usw. Die letzte Datei endet (nur) in einer Leerzeile.