LittleJunior
Anmeldungsdatum: 11. Oktober 2016
Beiträge: Zähle...
|
Hallo zusammen, ich möchte Textdateien für eine automatische Text-Filterung "zurecht stutzen".
Dafür müssen verschiedene Zeilen aus der Datei gelöscht werden. Beispielhafter Aufbau der Datei: Irgendetwas in '''Text''' 1
'''Text''' in dieser Reihe
weitere Zeilen
auch hier '''Text'''
noch mehr '''Text'''
'''Text''' in dieser
usw.
und noch mehr Zeilen
sogar weiter unten
gibt es '''Text'''
so sieht es aus Jetzt möchte ich das alle Zeilen in denen Text vorkommt gelöscht werden.
Aber erst nach dem 3. mal wo Text auftaucht. Probiert hab ich es schon mit: | sed -i '/Text/{2,$d}' Datei
|
→ die 2 bedeutet nur leider das die "Suche" erst in Zeile 2 beginnt | awk 'c&&!--c;/Text/{c=2};d' Datei
|
Mit grep hab ich zumindest die Ausgabe wie gewollt hinbekommen aber das Löschen wollte einfach nicht klappen :-/ Hoffentlich kann mir einer von euch helfen =) Gruß LittleJunior
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Hi LittleJunior, erstmal herzlich willkommen hier auf dem Forum ! Was ich noch nicht ganz verstehe: willst Du nur den 1. Treffer festhalten ? - Das ginge z.B. mit grep und head oder mit sed : track@track:~$ echo "$text" | grep Text | head -n1
Irgendetwas in Text 1
track@track:~$ echo "$text" | sed -n '/Text/{p; q}'
Irgendetwas in Text 1 oder willst Du den kompletten Text, nur ohne die 1. Trefferzeile ? - das würde dann etwas komplizierter. Das einfachste, was mir einfällt, wäre z.B. mit awk : track@track:~$ echo -"$text" | awk '/Text/ && x==0 {x=1; next} {print}'
Text in dieser Reihe
weitere Zeilen
auch hier Text
noch mehr Text
Text in dieser
usw.
und noch mehr Zeilen
sogar weiter unten
gibt es Text
so sieht es aus Oder, wenn es ab der 3. Zeile mit "Text" drin langweilig wird, dann sowas: track@track:~$ echo "$text" | awk '/Text/{x++; if(x>3) next} {print}'
Irgendetwas in Text 1
Text in dieser Reihe
weitere Zeilen
auch hier Text
usw.
und noch mehr Zeilen
sogar weiter unten
so sieht es aus LG, track n.b.: ein {{{Codeblock}}} geht hier auf dem Portal mit 3 Klammern ! 😉
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Er will alle Zeilen, in denen Text nicht vorkommt und die ersten 3, in denen Text vorkommt, behalten. Bzw. nicht ganz - die Zeilen mit den ersten 3 Vorkommnissen - also wenn es in der ersten Zeile 2 mal vorkäme, dann nur noch eine weitere Zeile mit fehlender Anweisung, was passieren soll, wenn das 3. u. 4. Vorkommen in der gleichen Zeile stattfindet. M.E. kein Job für sed. In Scala wohl so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | scala> val txt=scala.io.Source.fromFile("./test.txt").getLines.toList
scala> def print3timesText (t: List[String], cnt: Int=0) {
| if (t.isEmpty) ()
| else if (t.head.matches (".*Text.*") && cnt < 3) { println (t.head); print3timesText (t.tail, cnt+1)}
| else if (! t.head.matches (".*Text.*")) { println (t.head); print3timesText (t.tail, cnt)}
| else print3timesText (t.tail, cnt)}
print3timesText: (t: List[String], cnt: Int)Unit
scala> print3timesText (txt)
Irgendetwas in Text 1
Text in dieser Reihe
weitere Zeilen
auch hier Text
usw.
und noch mehr Zeilen
sogar weiter unten
so sieht es aus
|
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
user_unknown schrieb: ... Bzw. nicht ganz - die Zeilen mit den ersten 3 Vorkommnissen - also wenn es in der ersten Zeile 2 mal vorkäme, dann nur noch eine weitere Zeile mit fehlender Anweisung, was passieren soll, wenn das 3. u. 4. Vorkommen in der gleichen Zeile stattfindet. M.E. kein Job für sed.
Ooooch, mit ein bisschen hin- und hergeswappe mit dem Hold Space gehen tut das schon .... 🐸 .. 🐸 .. 🐸 .. Ist aber mehr was für Fortgeschrittene, und nicht so direkt intuitiv lesbar: 😀 track@track:~$ echo "$text" | sed -r '/Text/ {H; x; /(Text.*){4}/ {x; d}; x}'
Irgendetwas in Text 1
Text in dieser Reihe
weitere Zeilen
auch hier Text
usw.
und noch mehr Zeilen
sogar weiter unten
so sieht es aus
LG, track
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Ah, das ging flotter als mein Edit mit Scala. Also diese Holdgeschichte müsste mir mal wer erklären. Was ist das x, wo kommt es her?
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
user_unknown schrieb: Also diese Holdgeschichte müsste mir mal wer erklären. Was ist das x, wo kommt es her?
Der Holdspace ist der Hintergrundspeicher von sed → wird mit h bzw. H gefüllt. Das x ist der Swap- Befehl: Inhalt von Holdspace und Workspace (= die normale Zeile) gegeneinander vertauschen. Steht aber in meinem Link zum Holdspace auch nochmal ganz offiziell. LG, track
|
LittleJunior
(Themenstarter)
Anmeldungsdatum: 11. Oktober 2016
Beiträge: 6
|
WOW! Super lieben Dank für die schnellen Rückmeldungen! Das was track zum Schluss seines ersten Posts beschrieben hat ist genau das was ich gesucht habe Vielen Dank dafür. Und Sorry für die Ungenauigkeit was die Häufigkeit in der Zeile selber angeht 😉 Ich probiere das heute Abend/Nacht mal aus und melde mich dann wieder! Gruß LittleJunior
|
LittleJunior
(Themenstarter)
Anmeldungsdatum: 11. Oktober 2016
Beiträge: 6
|
So jetzt hab ich versucht das hier awk '/Text/{x++; if(x>3) next} {print}' mal umzusetzen aber leider kam dabei nichts raus... Was mir aufgefallen ist, ist das die Datei in der der Text steht gar nicht bearbeitet wird. Ich habe den Pfad der Datei in einer Variable TEXT gespeichert. Nur leider begreif ich nicht wie man jetzt awk sagt, es soll ab dem 3. Treffer (mehrere in einer Zeile egal) die ganzen Zeilen mit Treffer in der Datei löschen und speichern. Das ganze soll in einem Shell Script laufen. Ich blick leider nicht durch die ganzen kryptischen Zeichen durch hoffentlich könnt Ihr mir helfen. Gruß LittleJunior
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
LittleJunior schrieb: ... Ich blick leider nicht durch die ganzen kryptischen Zeichen durch hoffentlich könnt Ihr mir helfen.
Ah ja, nicht schlimm ... lies Dich einfach mal etwas im Skripting-Wiki ein, und guck Dir dort speziell das Thema "Pipe" an. Dann verstehst Du schnell, was ich da oben gebastelt habe, und wie Du den Befehl auch direkt auf Deine Datei anwenden kannst ! 2. Tip: zu ± jedem Befehl gibt es eine man - page, in der der Befehl genau dokumentiert ist. (→ direkt im Terminal: man [Befehl] ) - guck mal kurz in man awk rein, für Deinen Fall reichen schon die ersten Abschnitte. LG, track
|
LittleJunior
(Themenstarter)
Anmeldungsdatum: 11. Oktober 2016
Beiträge: 6
|
Perfekt hab es jetzt geschafft dank dir! ☺ Meine aktuelle Lösung sieht nun so aus: `awk '/Suchmuster/{x++; if(x>2) next} {print}' $Dateipfad > $Dateipfad'_NEU'` und dann halt wieder auf den alten Pfad ummodeln mit: cat $Dateipfad'_NEU' > $Dateipfad Jetzt habe ich nur noch ein weiteres Problem... Bei einem Suchmuster müssen 2 Zeilen die danach folgen gelöscht werden hab es hiermit versucht: TEST4=`awk '/Suchmuster/{x++; if(x>1) next} {getline; print; getline; print}' $Dateipfad > $Dateipfad'_NEU'` Jedoch löscht dieses Konstrukt leider auch andere Zeilen (z.B die allererste der Datei) Der Aufbau des Textes sieht so aus: Wieder irgendwelcher Text mit einem Suchmuster beim 2. Treffer wo das Suchmuster ist soll DIESE Zeile gelöscht werden dann folgt wieder noch mehr Text. was hab ich da falsch gemacht?
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12834
|
LittleJunior schrieb: Perfekt hab es jetzt geschafft dank dir! ☺
TEST4=`awk '/Suchmuster/{x++; if(x>1) next} {getline; print; getline; print}' $Dateipfad > $Dateipfad'_NEU'`
Ich gehe nur mal auf diese Zeile ein: was Du hier machst, ergibt keinen Sinn, weil Du nämlich die Ausgabe des Kommandos in eine Zeile umleitest und gleichzeitig versuchst, die Ausgabe in einer Variable zu sammeln. Das geht aber nicht, weil die Dateiumleitung erst zuschlägt und dann für die Variable nichts mehr übrig bleibt. Also, entweder lässt Du die Ausgabeumleitung weg oder das Sammeln in der Variable (die Command Substitution). Wenn Du wirklich beides willst, was in den seltensten Fällen sinnvoll ist, brauchst Du tee : | TEST4=$(command | tee datei.neu)
|
Und bitte nutze das passende Syntaxhighlighting.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
LittleJunior schrieb: TEST4=`awk '/Suchmuster/{x++; if(x>1) next} {getline; print; getline; print}' $Dateipfad > $Dateipfad'_NEU'`
.... ähm, so richtig hast Du das Skripting-Wiki nicht gelesen, oder ? Wie Robert auch schon sagt, stimmt das so einiges nicht.
Willst Du das Ergebnis in einer Variablen speichern oder wieder in einer Datei ? - das müsstest Du Dir schon überlegen. Wer hat Dir gesagt, dass Du diese unsäglichen, uralten `Backticks` verwenden sollst ? - das Wiki empfiehlt das jedenfalls nicht, und ich schon gar nicht. Wenn es jetzt komplizierter wird, solltest Du das awk - Skript auch unbedingt als Skript schreiben. Sonst verlierst Du die Übersicht. (Dein Einschub wird jedenfalls ohne Vorbedingung ausgeführt, also für alle Zeilen, und ich glaube, das wolltest Du gar nicht haben !)
Als Skript geschrieben sieht Dein awk - Dingens jedenfalls so aus: | #!/usr/bin/awk -f
/Suchmuster/ { x++;
if(x>1) next
}
{ getline; # diese Befehle werden für alle Zeilen ausgeführt, wenn der Programmlauf hier ankommt.
print;
getline;
print
}
|
... und jetzt überleg Dir noch einmal genau, unter welcher Bedingung Du was haben / machen willst ! LG, track p.s.: So langsam habe ich das Gefühl, dass Du mit den falschen Werkzeugen am tricksen bist, wenn Du (zufällig ?) die 2. Zeile nach dem 2. Treffer auch noch wegschmeißen willst 😲 Das kann doch nicht wirklich die Logik Deiner Daten sein ?! - vielleicht verrätst Du uns doch mal, was für Daten Du tatsächlich bearbeiten willst. Dann wird sich womöglich ein anderer, sinnvollerer Weg finden, die Daten gemäß ihrer tatsächlichen Logik zu verarbeiten ...
|
LittleJunior
(Themenstarter)
Anmeldungsdatum: 11. Oktober 2016
Beiträge: 6
|
Danke erstmal für Eure ganze Geduld! Ganz grob umrissen wird eine PDF-(Bilddatei) in Text umgewandelt und der Text anschließend nach Schlagworten durchsucht um an Daten zu kommen. Jede PDF kann aus 1 oder mehreren Bildern bestehen wobei jedes Bild eine gewisse Textstruktur z.B einen Header hat. Bei der Umwandlung von Bild zum Text entsteht 1 Textdatei (ist auch so gewollt). Es kann vorkommen, dass die Textdatei aus mehr als einem Bild entstanden ist. Dadurch kann es sein, dass die, für die Suche benötigte Stuktur, z.B durch den Header, aufgelöst wird. Deshalb müssen einige Textpassagen entfernt werden, damit die Struktur wieder hergestellt wird. Weil in dem Header leider auch individuelle Zeilen sind müssen diese mithilfe der fixen Suchbegriffe im Header gefunden und entfernt werden. Z.B. Weiss ich, dass nach dem Begriff SuchmusterABC in der Nächsten Zeile die gesuchte Information liegt. Einfach beide Header zu löschen ist keine Option, da auch hier Informationen zu finden sind deshalb benötige ich den 1. Header. Die Variable habe ich nur für den aktuellen Test eingerichtet, um mit dem ganzen awk/sed/grep die Ausgaben direkt einsehen zu können. Das mit den Backticks war mir nicht bekannt, ich habe das irgendwo bei einer Suche nach einer Abfrage gesehen deshalb schreib ich die dazu wenn die Ausgabe in einer Variable gespeichert wird. Und ja du hast Recht mein Einschub sollte jeweils nur auf jeden Treffer nach dem 1. angewendet werden. Viele Grüße LittleJunior
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Wenn ich Dich richtig verstehe, hast Du da also ein OCR- Projekt, bei dem Du die Scans von mehreren Seiten / Teilstücken anschließend wieder zusammensetzen willst. Und dabei gehst Du so vor, dass Du zuerst die einzelnen Seiten einzeln in Text umwandelst, und danach auf Text-Ebene versuchst, die (sich natürlich zum Teil überlappenden) Stücke zu bereinigen. Sehe ich das richtig ? Denn normalerweise würde man dieses aneinander-setzen ja gerade nicht auf der Text-Ebene, sondern bereits auf der Bild-Ebene machen. Denn da gibt es ja sehr viel mehr Merkmale, anhand der die Überlappung (→ durch Korrelation) eindeutig festgestellt werden kann. Praktisch hieße das:
die Scans zu einem einzigen Bild zusammenfügen, (z.B. mit Hugin ?) die OCR- Umwandlung wie gewohnt, aber dann von dem Gesamtbild
Wie gesagt, dieses "stitchen" auf der Textebene zu erledigen ist viel zu unsicher und mühsam (→ letztlich viel Handarbeit !), weil es einfach zu wenig sichere Merkmale gibt für das aneinanderpassen. Das so mal zum Grundsätzlichen. (aber ich kenne Dein Projekt ja nicht - vielleicht macht es ja trotzdem Sinn, wie Du da heran gehst ! - Dann will ich Dich auch gerne begleiten, wenn Du Dein awk - Ding baust.) LG, track
Nachtrag: Gerade noch ein anderer Gedanke: hast Du womöglich Scans aus einem Lexikon o.ä., wo die ständigen Kopfzeilen Dir einen Strich durch den Textfluss machen ?
Das wäre natürlich ein andere Fall, aber auch da würde ich diese Teile unbedingt schon auf Bildebene abschneiden, weil sie da noch hübsch durch den Abstand zum Textblock zu erkennen sind. Ein passendes Werkzeug dafür wäre z.B. convert von ImageMagick. Seitenzahlen erledigst Du auf dem selben Weg, nur falls es auch noch Fußnoten o.ä. gibt, wird es natürlich immer noch etwas Gebastel.
|
LittleJunior
(Themenstarter)
Anmeldungsdatum: 11. Oktober 2016
Beiträge: 6
|
Da hätte ich auch früher drauf kommen sollen 😳 Habe jetzt mittels convert und crop den betreffenden Teil entfernen können und alles läuft so wie es soll. Besten Dank für die ganze Hilfe! LG LittleJunior
|