Seite 1 von 1

python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Dienstag 20. März 2018, 12:32
von dark_universe
Hi Leute, ich bin neu hier und vesuche gerade mich in Python einzuarbeiten.
Könnte mir jemand helfen folgendes Perl command in Python umzubauen?
Zur Erklarung: Aus einem Text file sollen einfach die letzten Zeichen abgeschnitten werden, möchte aber kein Programm dazu schreiben sondern alles an der Unix shell machen. Das Perl-Commad lautet

cat Textfile.txt|perl -pe 's#(.*)(\d{6})#$1#' > Textfile.fixed

Das ist ( so ähnlich) im textfile eine Zeile und die letzen 6 Stellen aller Zeilen ( also das Datum: 201803 ) soll abgeschnitten/gelöscht werden:
12345656789345 5567 F345 123456400 0 0085201803

Wie würde ich das als Unix/Pyton Einzeiler schreiben?

Ich hoffe, Ihr könnt mir helfen

Gruß

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Dienstag 20. März 2018, 13:12
von Sirius3
@dark_universe: Python ist nicht ganz so kryptisch wie Perl, heißt, man muß da etwas ausführlicher programmieren. Weißt Du was Perl da macht? Das muß man dann durch explizites Lesen von der Standardeingabe und dem matchen eines Regulären Ausdrucks machen. Python-Einzeiler gibt es nicht.

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Dienstag 20. März 2018, 13:36
von darktrym
Schon Perl ist da zuviel, ein richtiger (schottischer) Administrator würde das in awk lösen.

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Dienstag 20. März 2018, 13:51
von DeaD_EyE
Ich denke das käme dem Perl Snippet am nächsten:

Code: Alles auswählen

import sys
import os
import re


regex = re.compile(r'.*(\d{6})$')

if not os.isatty(sys.stdin.fileno()):
    for line in sys.stdin:
        match = regex.search(line)
        if match:
            print(match.group(1))
Dann das Programm mit der Pipe verknüpfen:

Code: Alles auswählen

cat DATEI | python3 dein_filter.py
Mit awk wäre es kürzer. Neben awk gibt es noch nützliche tools wie z.B. cut und tr.
Ich bin damals vom Shell-Scripting weg, weil es mir zu viel Zeichensalat geworden ist.
Perl ist da nochmal eine Ecke kryptischer.

Re: python an der Unix shell mit cat command; process substitution

Verfasst: Dienstag 20. März 2018, 17:02
von dark_universe
Damit müsste es doch gehen: <(...) denotes process substitution. Das kommt dem ziemlich nahe kommt was ich brauche:

script.py <(awk '{if ($4 == 1975) print $1,$2,$3}' input.txt)

- für script.py muss ein Python 3 da sein
- das <( leitet die Übergabe an ein Unix comand ein wie awk, grep oder sed
- in dem Bsp. werden alle Zeilen ausgegeben, die in der 4. Spalte ein 1975 haben

Allerdings scheitere ich schon daran, das spript.py aufzurufen. Python 3 liegt bei uns im /opt/.../python3 Verzeichnis.
Das inputfile sieht so aus:
D000001 D000001 44 1975
D000001 D000408 1 1983
D000001 D000641 1 1977
D000001 D000900 27 1975

Das awk komado alleine liefert
D000001 D000001 44
D000001 D000900 27
und der Python Teil schreibt das ganze in ein file? Hier brauche ich mal eure weitere Hilfe, damit mal das Bsp. läuft und dann gehts mit meinem Problem weiter.

Danke

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Dienstag 20. März 2018, 17:30
von kbr
Mit Python geht das auch kurz und knapp:

Code: Alles auswählen

import sys

for line in sys.stdin:
    sys.stdout.write(line.rstrip()[:-6] + '\n')
Angenommen obigen Code speicherst Du als 'fix.py' ab, dann führst Du das aus mit

'$ python fix.py < textfile.txt > textfile.fixed'

Falls Du die Shebang-Zeile gesetzt und die Datei als executable markiert hast, kannst Du auch die Extension weg lassen:

'./fix < textfile.txt > textfile.fixed'

Dies gilt für Dein erstes Beispiel, die letzten sechs Zeichen zu entfernen. Das kannst Du natürlich beliebig modifizieren oder auch gegen mögliche Fehler absichern.

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Mittwoch 21. März 2018, 09:13
von dark_universe
Ok, vielen Dank, werde ich heute ausprobieren

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Mittwoch 21. März 2018, 12:02
von dark_universe
So, hat geklappt, habe die Lsg von kbr mit line.rstrip()[:-6] umgestzt. Die konnte ich einfach nachvollziehen, das von DeaD_EyE war mir erst mal zu komplziert.
Danke auch an die anderen, die mir Wertvolle Tipps gegeben haben.
Gruß

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Mittwoch 21. März 2018, 14:20
von sebastian0202
Hallo,


mit sed geht das auch!
Wobei zu beachten ist, dass mit der Option -i, die Änderungen direkt übernommen werden.

[codebox=bash file=Unbenannt.bsh]
sed -i -r 's/(.*)[A-Z0-9 ]{6}$/\1/' test.txt
[/code]

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Donnerstag 22. März 2018, 11:42
von dark_universe
Hallo nochmal,
bei genauem Betrachten der Lsg, von kbr mit line.rstrip()[:-6] gibt es noch 2 Probleme.

1. in jedem Zeilenende gibt es ein ^M ( 00123654321^M) das ich gerne erhalten möchte/muß oder am Ende wieder hinzufügen muss.

2. Jedes file das ich bearbeiten muss hat einen
a) Header,
b) dann kommen die Daten, wo jetzt die letzen 6 Zeichen gelöscht werden sollen
c) einen Trailer.

Header und Tailer sollen nicht verändert werden, die Datengröße oder besser die Anzahl der Zeilen dazwischen sind variabel, also mal 1000 Zeilen mal 50 000 Zeilen.

Wie würde ich da vorgehen? Erst mal die Zeilen der Datei zählen und dann erste und letzte Zeile von der Bearbeitung ausschließen?

Danke und Gruß

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Donnerstag 22. März 2018, 13:09
von Sirius3
@dark_universe: das ^M kommt daher, dass Du DOS/Windows-Zeilenenden hast. Einfach statt '\n' -> '\r\n' schreiben. Bisher ignorierst Du ja Header und Trailer und löscht einfach die letzten 6 Ziffern, die Du in jeder Zeile findest (egal ob sie am Zeilenende stehen oder nicht). Sauberer wäre es dann tatsächlich, Header und Trailer gesondert zu behandeln. Woher erkennt man denn, was Header und was Trailer ist?

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Donnerstag 22. März 2018, 15:17
von IHack

Code: Alles auswählen

sed -rn 's/(.+)[[:digit:]]{6}$/\1/;p' path/to/your/inputfile
Entfernt 6 dezimale Ziffern am Ende einer Zeile. Und nur, wenn es wirklich 6 sind.
Und sed sollte auf so ziemlich jedem *nix verfügbar sein.

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Donnerstag 22. März 2018, 15:25
von Sirius3
@IHack: das funktioniert nicht, wenn, wie der OP sagt, ein Carriage-Return am Ende jeder Zeile steht. Einfacher wäre es dann auch, einfach nur die letzten 6 Zahlen durch nichts zu ersetzen:
[codebox=bash file=Unbenannt.sh]
sed -rn 's/[[:digit:]]{6}\s*$//;p' path/to/your/inputfile[/code]

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Donnerstag 22. März 2018, 16:45
von dark_universe
@Sirius3:
Header und Trailer erkennt man nicht so einfach. Man weiss das sie am Anfang/Ende sind.

Deswegen würde ich wie folgt vorgehen für sagen wir mal 1000 files mit jeweils 100 - 100 000 Zeilen:
1. File1 öffnen und und Zeilen zählen: erste Zeile ist n, letzte nMax -> erste Schleife
2. for- Schleife mit dem Script vonb kbr:
import sys

for line in sys.stdin:
sys.stdout.write(line.rstrip()[:-6] + '\n')


und in der Schleife von n+1 bis nMax-1 laufen lassen
3. beide Schleifen schliessen
4. File2 öffnen und weiter gehts ...

Könnt Ihr mir mal helfen, wie dazu das äussere Phyton Programmier-Gerüst auszusehen hat, das wäre klasse.

Re: python an der Unix shell mit cat command; umsetzten eines Perl Befehls nach Python

Verfasst: Donnerstag 22. März 2018, 21:07
von kbr
@dark_universe: Ob header und tailer einfach oder schwer zu erkennen sind, ist völlig egal. Wenn sie vorhanden sind, musst Du sie erkennen. Sonst kannst Du keine Fallunterscheidung bezüglich der zu bearbeitenden Zeilen treffen.
Wenn Du weißt, dass der header genau eine Zeile beträgt, dann ist das kein Problem – Du überspringst die Zeile einfach. Beim trailer ist das anders: da brauchst Du eine Mustererkennung. Oder, falls der trailer auch nur eine Zeile beträgt, pufferst Du die zu bearbeitende Zeile zunächst, um zu sehen, ob noch eine weitere nachfolgt. Eigentlich eine prima Übung.