Suche Python-Find-and-Replace-Script

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Eines vorab: Das ist keine Bitte um Hilfe bei der Programmierung eines Find-and-Replace-Scripts. Ich kann mir nur vorstellen, dass es ein fertiges und kostenloses Script für meinen Zweck gibt, weil es sich bei dem Zweck um Standard-Aufgaben handelt, die jeder, der hin und wieder codet zu erledigen hat. Meine Google-Suche nach einem solchen Script ist bislang ergebnislos.

Ich suche also ein fertiges Python-Find-and-Replace-Script, dessen Lizenz die Modifikation und Weitergabe erlaubt.

Das Script soll eine oder mehrere Zeilen Text in Text-Dateien (z. B. .ttx [xml] oder .txt) ersetzen können. Und der zu findende und zu ersetzende Text soll mit Hilfe eines Bash-Scripts übergeben werden können. Reguläre Ausdrücke sollten möglich sein.

Ich will mit dem Script mit den FontTools dekompilierte Fonts kommentieren, z. B. die die Namercords in der Name-Table von TrueType- und OpenType-Fonts. (Unkommentiert ist die Ausgabe angesichts der Vielzahl der Namerecords zu unübersichtlich. Ohne Kommentare muss man ständig die OpenType-Spezifikation vor Augen haben.) Außerdem soll damit der Platzhalter "type/subtype", den ich in das Base64-Script von Sirius3 "eingebaut" habe, über ein Bash-Skript mit dem korrekten MIME-Type ersetzt werden.

Bisher habe ich das Tool SSR dafür verwendet. Aber zum einen darf ich das nicht einfach weitergeben und zweitens ist das ein reines Windows-Tool.
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

Gegenfrage: sed tut es nicht?
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Vermutlich schon. Aber das müsste unter Windows installiert werden, oder?

Python ist auf jeden Fall schon vorhanden, weil es Bestandteil des AFDKO (Adobe Font Developent Tools for OpenType) ist.

Das, was ich in dem Zusammenhang an Python-Scripten bei meiner Google-Suche gefunden habe, deutet darauf hin, dass die Python-Lösung am Einfachsten und besonders kompakt wäre.

SSR tut es ja auch. Damit bin ich selbst vollauf zufrieden. Ich habe nur letztens jemandem auf GitHub mein Batch-Script mit den Kommentaren der Name-Table gegeben, weil der den Wunsch an die Entwickler der FontTools geäußert hatte, den Decompiler (TTX) den Output selbst kommentieren zu lassen. Und der hätte sich dann entweder SSR herunterladen oder mein Batch-Script an sein Find-and-Replace-Tool anpassen müssen. Schöner wäre es, wenn ich in solchen Fällen ein kleines Tool w. z. B. das angedachte Python-Find-and-Replace-Script einfach direkt übergeben könnte. Denn wer die FontTools nutzt, hat auf jeden Fall auch Python installiert.
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

kyou hat geschrieben:Vermutlich schon. Aber das müsste unter Windows installiert werden, oder?
Okay, da du im vorherigen Post was von Bash-Skript geschrieben hast, war ich jetzt davon ausgegangen, dass das nur in einer unixoiden Unmgebung (inkl. Cygwin) laufen soll. Es gibt zwar Windows-Varianten von sed (etwa hier), aber du müsstest die dann halt auch mitliefern; hat gegenüber deiner bisherigen Lösung den Vorteil, dass es nicht nur unter Windows, sondern beispielsweise auch Linux und OS X laufen würde (ohne etwas zu installieren), ist aber zugegeben unter Windows etwas sperriger, als mit vorinstallierten Sachen zu arbeiten.
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Okay, da du im vorherigen Post was von Bash-Skript geschrieben hast
Korrigiere ich. Batch-Script.
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Ich habe den Hauptentwickler der FontTools jetzt mal gefragt, ob er nicht Lust hat, ein Search and Replace Script zu schreiben und in die FontTools zu integrieren. Der kann mich zwar nicht leiden, weil ich nur User bin, aber vielleicht sieht er ja ein, dass so ein Script nützlich wäre. :)
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

Hast du mal geschaut, ob eines der Skripte die im PyPi verzeichnet sind sich für deine Zweck eignen?
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Ne, aber das ist ein sehr guter Tipp! Da springen mir ja direkt ein paar Scripts ins Auge, die der Beschreibung nach geeignet sein könnten. Danke! Werde ich durchsuchen. Kennst du noch andere Script-Archive, in denen ich suchen kann?

Ich denk nicht, dass die Entwickler der FontTools so ein Script integrieren oder sogar schreiben werden. Und erst mal hat das ja auch wenig mit Fonts zu tun. Insofern nachvollziehbar.

Übrigens wäre Perl eventuell noch eine Alternative. Ich habe das zumindest installiert, weil das AFDKO auch ein paar nützliche Perl-Scripts (z. B. im Zusammenhang mit Hinting) enthält. Ich vermute aber, dass die wenigsten User diese Scripte schonmal eingesetzt und deswegen Perl nicht installiert haben.
nezzcarth
User
Beiträge: 1635
Registriert: Samstag 16. April 2011, 12:47

kyou hat geschrieben:Ne, aber das ist ein sehr guter Tipp! Da springen mir ja direkt ein paar Scripts ins Auge, die der Beschreibung nach geeignet sein könnten. Danke! Werde ich durchsuchen. Kennst du noch andere Script-Archive, in denen ich suchen kann?
Abgesehen von den üblichen Ablagestellen für Code (github, bitbucket, launchpad usw.) leider nicht.
Übrigens wäre Perl eventuell noch eine Alternative. Ich habe das zumindest installiert, weil das AFDKO auch ein paar nützliche Perl-Scripts (z. B. im Zusammenhang mit Hinting) enthält.
Perl kann so etwas in der Richtung schon von sich aus:

Code: Alles auswählen

$ cat test.txt
123
456
789


$ perl -pe 's/^/# /' test.txt
# 123
# 456
# 789
(Die Syntax ist in dem Fall übrigens von sed übernommen)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich hab sowas mal gemacht:

https://github.com/jedie/python-code-sn ... n_files.py

Das zeigt dir dann auch den DIFF an.

Vielleicht auch interessant:
https://github.com/jedie/python-code-sn ... n_files.py

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

@ jens

Danke. Kann ich per Batch-Script die Optionen "Infile", "search string" und "replace string" übergeben oder müssen diese Angaben direkt in das Script geschrieben werden?

Bisher habe ich das mit SSR und Batch so realisiert:

[codebox=dos file=Unbenannt.bat]set "L=/SSR_NL/"

for %%f in (DecompileD\*.ttx) do (

%ssr_exe% 0 " <macStyle" "%L%<!-- Check also fsSelection in OS2-table. -->%L%<!-- macStyle value=''00000000 00000000''/ for Upright -->%L%<!-- macStyle value=''00000000 00000010''/ for Italic -->%L%<!-- macStyle value=''00000000 00000001''/ for Bold -->%L%<!-- macStyle value=''00000000 00000011''/ for Bold Italic -->%L% <macStyle" "%%f"
)[/code]

"/SSR_NL/" bewirkt eine neue Zeile.

In dem Beispiel wird nur eine von derzeit etwa 80 Ersetzungen durchgeführt. (Im Beispiel geht es um die Kommentierung einer der beiden für das Font-Style zuständigen Sektionen.

Vielleicht wird jetzt auch verständlich, warum man angesichts dieses Outputs von TTX [dekompilierte Fonts] die OpenType-Spezifikation vor Augen oder im Kopf haben muss, um Änderungen vornehmen zu können. Deswegen schreibe ich quasi Teile der Spezifikation als Kommentare in die dekompilierten Fonts. Und mir ist das sogar lieber so, als wenn der Output von TTX weniger kryptisch wäre, weil man auf die Weise besser lernt, die Spezifikation zu verstehen.

Bei der Rekompilierung der Fonts werden die Kommentare dann einfach übergangen.)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ein CLI hat mein Skript nicht. Könnte man natürlich bauen...

Benutzung siehe Beispiel im Code:

Code: Alles auswählen

from replace_in_files import SearchAndReplace

SearchAndReplace(
    search_path = "/to/the/files/",

    # e.g.: simple string replace:
    search_string  = 'the old string',
    replace_string = 'the new string',

    # e.g.: Regular expression replacing (used re.sub)
    #search_string  = re.compile('{% url (.*?) %}'),
    #replace_string = "{% url '\g<1>' %}",

    search_only = True, # Display only the difference
    #search_only = False, # write the new content

    file_filter=("*.py",), # fnmatch-Filter
)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Verstehe. Hab's gerade kurz getestet. Aber nur ein Wort ersetzt. Damit muss ich erst mal ein wenig herumexperimentieren.

Wenn die zu findenden und ersetzenden Zeichen im Python-Script enthalten sind, hat das zumindest den Vorteil, dass es kein Batch-Script gibt, das an Nicht-Windows-Betriebssysteme angepasst werden muss.

Außerdem: Bestimmte Zeichen sind in Batch-Dateien gar nicht erlaubt, oder? Die ließen sich also gar nicht ersetzen. Aber vielleicht erinnere ich mich da auch falsch.
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

@ Jens

Code: Alles auswählen

SearchAndReplace(
    search_path = "/to/the/files/",
 
    # e.g.: simple string replace:
    search_string  = 'the old string',
    replace_string = 'the new string',
 
    # e.g.: Regular expression replacing (used re.sub)
    #search_string  = re.compile('{% url (.*?) %}'),
    #replace_string = "{% url '\g<1>' %}",
 
    search_only = True, # Display only the difference
    #search_only = False, # write the new content
 
    file_filter=("*.py",), # fnmatch-Filter
)
muss man für jede Ersetzung komplett "wiederholen". Nur die "Wiederholung" von

Code: Alles auswählen

    search_string  = 'the old string',
    replace_string = 'the new string',
reicht nicht.

Das bläht das Script ziemlich auf bei meinen derzeit 80 Ersetzungen.

Ansonsten käme ich damit gut klar.


Edit:

Ich kann mir aber vorstellen, dass es mir gelingt das zu ändern. Ein wenig habe ich ja schon gelernt, als ich mich mit dem Base64-Script auseinandergesetzt habe. Also dadurch, dass ich versucht habe, die Änderungen von Sirius3 nachzuvollziehen. Ich schau mir das morgen nochmal an.

Jedenfalls bestätigt mich das Ganze in der Vermutung, dass es das Beste ist, die Ersetzungen mit Python zu realisieren.
----------------------

Du hast übrigens zweimal denselben Link in deinem vorletzten Beitrag gepostet. Wolltest du noch einen Link zu einem anderen Script posten?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

kyou hat geschrieben:muss man für jede Ersetzung komplett "wiederholen". Nur die "Wiederholung" von

Code: Alles auswählen

    search_string  = 'the old string',
    replace_string = 'the new string',
reicht nicht.

Du meinst mehrere suchen&ersetzten gleichzeitig machen?!? Ja, das geht nicht direkt. Evtl. per regex...
Aber ja, hast somit eine Aufgabe, es in Python zu lösen. So lernt man Python bei der Praxis...



kyou hat geschrieben:Du hast übrigens zweimal denselben Link in deinem vorletzten Beitrag gepostet. Wolltest du noch einen Link zu einem anderen Script posten?
Stimmt. Ich wollte noch auf https://github.com/jedie/python-code-sn ... n_files.py hinweisen. Ich hab es oben geändert.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

@ Jens

Als ich selbst nach so einem Script gesucht hatte, hatte ich diejenigen Scripts nicht berücksichtigt, denen man keine Argumente per Batch-Script übergeben kann, also solche Scripts wie deines, Jens.

Deswegen werde ich nochmal suchen.

Wie gesagt: Mit der Argparse-Konstruktion scheinen sich Argumente recht leicht hinzufügen zu lassen. Deswegen glaube ich, dass es mir gelingen wird, dein Script entsprechend zu erweitern.

Was ich allerdings gerne hätte, wäre eine Option, über die ich entscheiden kann, ob alle Vorkommen eines Ausdrucks ersetzt werden sollen oder nur der erste gefundene. TTX-Dateien können nämlich ziemlich groß sein. Man kann zwar mit TTX gezielt nur bestimmte Tables decompilieren, die Name-Table ist z. B. vergleichsweise klein. In dem Fall macht sich der Geschwindigkeitsunterschied kaum bemerkbar. Decompiliert man aber einen großen Font komplett, kann auf die Name-Table noch sehr viel Text folgen, den dein Script dann unnötigerweise auch durchsuchen würde.

Dass es mir selbst gelingt, das Script in Bezug auf die Anzahl der Vorkommen der Ausdrücke zu modifizieren, glaube ich eher nicht.
So lernt man Python bei der Praxis...
Das liegt mir auch eher, als irgend welche Tutorials abzuarbeiten, in denen es um Scripts geht, die für Aufgaben zuständig sind, die mich absolut nicht interessieren.

--------------------------------

Mir ist aber gestern noch etwas anderes durch den Kopf gegangen. Mal angenommen, ich bräuchte ein Script wirklich dringend für mich selbst. Dann könnte ich fragen, wie teuer es wäre, so ein Script programmieren zu lassen. Dann den Preis um einen bestimmten Faktor senken, dem Forum als Spende zukommen lassen und hoffen, dass das einen oder mehrere Programmierer im Interesse des Forums motiviert, das Script zu programmieren. Mit Forum ist in dem Zusammenhang der Betreiber gemeint. Den der Betrieb eines Forums kostet ja Geld. Und die Bedingung wäre, dass das Script dann eine Lizenz hat, die die Weitergabe und Modifikation erlaubt, also nicht exklusiv ist. Das Ganze würde also jederzeit öffentlich ablaufen. Ob sich dann jemand findet, den das motiviert, hängt stark davon ab, für wie viele Leute das Script nützlich wäre. Ein Find-and-replace-Script ist z. B. für sehr viele Leute nützlich. Deswegen kann ich mir vorstellen, dass das Konzept in diesem Fall aufginge.

Ich habe das zwar in Bezug auf das Find-and-replace-Script wieder verworfen, aber nur deshalb, weil ich für meine eigenen Font-Modifikationen auch ohne ein solches Script auskomme. Denn es klappt ja prima mit SSR.

Aber ich finde die Idee nicht schlecht.
kyou
User
Beiträge: 50
Registriert: Sonntag 7. November 2010, 08:38

Ich habe vor einigen Tagen ein Find-and-Replace-Script gefunden, das sich so steuern lässt, wie ich mir das vorgestellt habe. Zumindest, soweit ich es testen konnte, weil es im Moment noch einen Fehler (Error 32 unter Windows) hat. Ich bin aber zuversichtlich, das der Autor den Fehler korrigiert und das Skript vielleicht sogar noch um eine reine Suchfunktion ergänzt.

Siehe github.com/msztolcman/subst.
Antworten