Komplex: PDF separieren mittels bash

R

r00ki3

Jungspund
Hi ihrs,

ich suche nach einer Möglichkeit, eine große PDF - Datei mittels bash in einzelne, teilweise zusammenhängende Seiten zu zerlegen. Dies soll unter Berücksichtigung best. Kriteria in der PDF geschen.

Ich kam auf die Idee, die Datei zunächst einmal mit [pdftotext] nach ASCII zu strippen, um ein ganzzahliges Eindeutigkeitsmerkmal auf einer jeden Seite isolieren zu können, welches innerhalb der einzelnen Seiten manchmal wechselt. Dieses steht in der ASCII - Datei immer in Zeile 15 alleine.

Sobald dieses sich ändert, möchte ich das PDF am vorigen ( ! ) Seitenumbruch
absägen ( Prinzip Klorolle :)) ) , genauergesagt die Nummer der Seite in
eine Datei oder eine Variable schreiben, um anhand dieser Daten die Dateien
später trennen zu können ( gs oder pdftk ) und sie anhand des isoierten Eindeutigkeitsmerkmals benennen und weiterverabeiten zu können.

Kann mich mal jemand in die Richtige Richtung schubsen ?
Meine Idee wäre, die Seitenumbrüche zu extrahieren und mitzuzählen, aber ich weiß
nicht wie ich das in bash ausdrücke. Mit while read ... do ?

r00ki3
 
Zuletzt bearbeitet:
Wenn es nicht unbedingt bash sein muss, erfuellt dann nicht pdftk eventuell Deine Wuensche? Kannst es ja auch in in bash-skript einbinden. Oder sollen es am Ende Text-Dateien sein?
 
Hi zusammen,

ja, das pdftk ist gewiß das richtige Tool dafür - ich glaube aber, ich hab mich falsch oder unvollständig ausgedrückt ( mea culpa ).
Mein Problem ist nicht, nicht zu wissen ob uns wie pdftk Seiten separiert, sondern nicht
zu wissen, wo ( ! ) ich in der Quelldatei durch es die Schere ansetzen muss. Es ist mir unbekannt, auf welcher Seite sich das Eindeutigkeitmerkmal ändert - ergo weiß ich nicht, wo ich trennen muss. pdftk enthält m. E. keine Möglichkeit, PDFs nach inneren ( ! ) Kriterien zu scannen, um Trennpunkte festzulegen.

Ein Beispiel:

Unser Controlling gibt eine 300 - seitige PDF aus, die auf dem Linux - Host landet. Das sind die zu verarbeitenden Rohdaten. Es handelt sich bei den Quelldaten um Zeiterfassungsnachweise für Mitarbeiter, die stets unterschiedlich lang ist und verschiedene, sich ändernde Namen beinhaltet.
Dieses gilt es zu berücksichtigen.

Ich sauge hierfür zuerst unter bash im fraglichen Skript mittels pdftotext den ASCII - Klartext heraus und finde die Trennpunkte:

  • auf den ersten drei Seiten in Zeile 15 die Personalnummer 12345.
  • auf Seite vier bis sechs in Zeile 15 die Personalnummer 23456
  • auf Seite sechs bis zehn zehn in Zeile 15 die Personalnummer 34567.
  • und so weiter...bis zum Ende

Aus einer großen PDF - Datei entstehen somit einzelne Häppchen, deren
Anzahl und Größe vorher unbekannt ist, da ich nicht weiß wieviele
Leute da drin stehen ( was sich ebenfalls ändert ).

Für pdftk bedeutet das:

  • Erzeuge mir einzelne PDF - Dateien aus den hier genannten Seiten analog zu Anzahl der gefundenen EIndeutigkeitsmerkmale.
  • Stelle somit sicher, daß jeder Mitarbeiter nur seine eigenen Seiten bekommt.

Diese Info will ich an pdftk ( pdftk burst innerhalb bash übergeben.
Wenn ich im Vorfeld wüßte, welcher Mitarbeiter wieviele Seiten ab welcher Position im Quell - PDF bekommt, wäre es kein Thema.Diese Info muss ich aber m. E. zuerst in Form einer Steuerdatei gewinnen, um pdftk mitteilen zu können, wo es die Schere ansetzen soll. Die Trennmarken sind, einfach ausgdrückt, dynamisch, nicht statisch.


Lieben Gruss vom

r00ki3
 
Zuletzt bearbeitet:
Hi,

ich weiss nicht, ob ich dich richtig verstanden hab, aber du musst doch sowas machen:
Code:
old_pnr = irgendwas
seitenzaehler =0
while (dokument nicht zu ende)
        if(pers_nr == old_pnr)
                  seitenzaehler++
        else 
           old_pnr = pers_nr
           seitenzaehler irgendwo speichern
           seitenzaehler auf 1 setzen

Sorry, ich kann aus dem Stehgreif keinen richtigen bash-code schreiben :-).
 
Hallo

Da ich die Daten nicht kenne, kann ich schlecht etwas sagen dazu.
Wie sieht denn der ASCII -File aus?
Woran erkennst du denn in dieser Datei , dass eine neue Seite angefangen hat?
Steht die Personalnummer immer an der gleichen Stelle?
Viele Fragen, ohne die ich einfach nicht wirklich helfen kann.

Gruß Wolfgang
 
Wolfgang schrieb:
Hallo

Da ich die Daten nicht kenne, kann ich schlecht etwas sagen dazu.
Wie sieht denn der ASCII -File aus?
Woran erkennst du denn in dieser Datei , dass eine neue Seite angefangen hat?
Steht die Personalnummer immer an der gleichen Stelle?
Viele Fragen, ohne die ich einfach nicht wirklich helfen kann.

Gruß Wolfgang
r00ki3 schrieb:
Dieses steht in der ASCII - Datei immer in Zeile 15 alleine.
ey, steht doch da, Mann: Immer in der 5. Zeile, wenn man die PDF-Datei seitenweise in ASCII umwandelt, und dort voellig verlassen...
 
rikola schrieb:
ey, steht doch da, Mann: Immer in der 5. Zeile, wenn man die PDF-Datei seitenweise in ASCII umwandelt, und dort voellig verlassen...
Ich lese da nur etwas von Zeile 15.
Ob es dort einsam und alleine steht, lese ich nicht.
Ob die Datei seitenweise in einzelne Stücke konvertiert wird auch nicht...
Dann müsste zumindest erstmal sichergestellt werden, dass die einzelnen ASCII Dateien in der richtigen Reihenfolge verfüttert werden.
Wenn nicht, muss erstmal festgestellt werden wieviele Zeilen zu einer Seite gehören... usw.
Also ist aus meiner Sicht bisher alles recht spekulativ.

Die 15.Zeile aus einer Datei kann man mit sed in eine Variable einlesen:
Code:
VAR="$(sed -e '15d' datei)";

Naja, eventuell kommen ja noch einige Hinweise.

Gruß Wolfgang
 
Wolfgang schrieb:
Ich lese da nur etwas von Zeile 15.
Ob es dort einsam und alleine steht, lese ich nicht.

Ist zwar wohl nicht ganz so wichtig, aber im 1. Post steht doch im letzten Satz des 2. Absatzes ganz eindeutig allein. Oder?

Andrea
 
Andrea schrieb:
Ist zwar wohl nicht ganz so wichtig, aber im 1. Post steht doch im letzten Satz des 2. Absatzes ganz eindeutig allein. Oder?

Andrea
Ja, dass das im ersten Posting schonmal stand, habe ich überlesen.

Trotzdem bleiben die anderen Fragen stehen.
Die Syntax, die Zeile 15 absolut vom Dateianfang! in eine Variable zu sichern, habe ich ja schon geschrieben.
Wenn alles in einer ASCII-Datei steht, dann muss zumindest feststehen, wieviel Zeilen zu einer Seite gehören.
Anders ist eben nicht feststellbar auf welcher Seite man sich befindet.:think:

Also könnte man mit diesem Wissen die große Datei immer seitenweise in ein Array einlesen (Zeilen Zählen) und das 15.-te Element untersuchen.
Abhängig davon, ob diese sich geändert hat den Inhalt des Arrays in eine neue Datei schreiben oder anhängen. usw.

Aber alles sehr abstrackt.

Gruß Wolfgang
 
Hallo ihr lieben,

besten Dank und sorry für das WM - bedingt verspätete Feedback.
Wolfgang, hier für dich ein paar Infos:

pdftotext [INFILE.PDF] --> [OUTFILE.TXT] [OK].
Ergebnis ist: Die Personalnummer steht in der OUTFILE.TXT...

* als 5 - stellige Ganzzahl
* alleine links am Zeilenanfang jeder 15. Zeile jeder Seite.
* sie steht immer genau dort und ändert nicht ihre Position.

In der outfile.txt sind die Seitenumbrüche sichtbar ( dies ist auch mit pdftotext -nopgebrk [...] abschaltbar ); das Ergebnis ist die Ausgabe von ^L in der outfile.txt an den Positionen der Umbrüche. Angeblich ist das das Zeichen 0x0. Eine Seite in der ASCII - Datei hat immer 294 Zeilen ASCII - Rohtext; die Seitenzahl der ASCII - Datei ist somit identisch zu der INFILE.PDF.

Das ^L wird bei less invers dargestellt; bei vi in blau und in der Fusszeile von vi steht [noeol]. Ein grep -e ^\^ outfile.txt führt leider (noch) zu nichts.

Wolfgang, der sed - Befehl schreibt bei sed [...] > test.txt die outfile.txt komplett > test.txt....


Lieben Gruß vom
r00ki3
 
Zuletzt bearbeitet:
Hallo

Ja ich habe bei meinem sed befehl leider das Negationszeichen vergessen (Fiptehler) ;)

Also die 15. Zeile absolut erhältst du natürlich mit
Code:
sed -e '15!d' datei
Das wird dir aber wenig nutzen.
Du solltest also einen Zeilenzähler mitlaufen lassen.
Auf die 15. Zeile jeder Seite kommst du bei konstanter Zeilenzahl pro Seite, indem du mit MOD-> aktuelle Zeile %Zeile pro Seite arbeitest und nach dem Wert 15 abfragst.
Code:
ZEILE=0;
while read NUM REST; do
$ZEILE=$(($ZEILE +1))";

if [ "$ZEILE" % 296 -eq 15 ];
then
NUMER=$NUM;
fi
done < Datei
Um auf ^L also formfeed ( in der bash auch \f) mit grep zu matchen brauchst du z.B. folgendes:

Code:
 echo $'Achtung\nSeiten\n\f\n-wechsel'|egrep  '[[:cntrl:]]'

Gruß Wolfgang
 
@Wolfi: echo $'\f' und echo -e '\f' nimmt sich nichts - ist identisch - right? :D
 
Hallo Wolfgang,

Auf die 15. Zeile jeder Seite kommst du bei konstanter Zeilenzahl pro Seite, indem du mit MOD-> aktuelle Zeile %Zeile pro Seite arbeitest und nach dem Wert 15 abfragst.
Code:
ZEILE=0;
while read NUM REST; do
$ZEILE=$(($ZEILE +1))";

if [ "$ZEILE" % 296 -eq 15 ];
then
NUMER=$NUM;
fi
done < Datei


Die Variablen NUM und REST "entnimmst" du wo ? Ich kenne diesen Befehl nur in dem Zusammenhang, daß ich aus einer externen Datei zeilenweise lese und
diese Werte für das Füllen einer Variable nutze. Ich sehe ( ! ) hier keinen Zusammenhang, aber hier ist mein Nickname wohl Programm :D

Der Befehl if [ "$ZEILE" % 296 -eq 15 ]; überprüft auf Gleichheit ?


Lieben Gruss vom

r00ki3
 
Ok, Danke ( den Wald vor Bäumen nicht gesehen )

if [ "$ZEILE" % 296 -eq 15 ]

gibt jedoch unexpected EOF while looking for matching `"'
zurück, woran mag das liegen ?
 
r00ki3 schrieb:
Ok, Danke ( den Wald vor Bäumen nicht gesehen )

if [ "$ZEILE" % 296 -eq 15 ]

gibt jedoch unexpected EOF while looking for matching `"'
zurück, woran mag das liegen ?
Das lässt sich so einfach nicht sagen, weil es davon abhängt wie deine Daten ausschauen.
Lass dir doch mal die Variable $ZEILE ausgeben.
Könnte es sein, dass die Daten im Dos/Windows-format vorliegen, oder binäre Daten enthalten?

Aber zu dem Format habe ich ja schon weiter oben etwas gesagt.

Gruß Wolfgang
 
Das kommt von einem Tippfehler. Zähl mal die Anführungszeichen.

---edit---
hier speziell: $ZEILE=$(($ZEILE +1))";
---edit---


Gruß
 
Zurück
Oben