Seite 1 von 1

Textbausteine

Verfasst: Freitag 30. Oktober 2009, 16:59
von steffan
hallo,

ich möchte ein Programm schreiben, bei dem ich in vorhanden C-Code Namen austausche.

Als Beispiel:
in einer textdatei (oder sonstigen Datei) steht Code wie...
Name=2*4; //Name ist nur ein Platzhalter

jetzt will ich mit Python den Code lesen, "Name" ersetzten und den neuen Code in eine .c-Datei schreiben. Die C-Datei könnte dann so aussehen:

Window=2*4; //"Name" wurde durch "Window" ersetzt


Ich bin neuling in Python und hab jetzt ein Turorium hinter mir, aber ich sehe noch nicht wie ich das lösen kann.

Was für Befehle würden sich da anbieten?

danke

Verfasst: Freitag 30. Oktober 2009, 17:09
von Hyperion
Hier kommt es nicht auf "Befehle" an, sondern zunächst einmal auf die geeigneten Strategie.

Refactoring ist nicht ganz so trivial wie man zunächst denken würde:

Code: Alles auswählen

// 'bar' auf globaler Ebene
int bar = 1;

void foo() {
    // noch eine Variable namens "bar"
    int bar = 42;
}
Was würde passieren, wenn man nur nach "bar =" suchen würde? Man würde ja beide finden und entsprechend ersetzen - dabei sind das ja zwei vollkommen unterschiedliche Bezeichner.

Für die einfache Lösung, die das obige Problem vermutlich nicht lösen können wird, könntest Du über einen einfachen RegExp nach dem Konstrukt "<Bezeichner><beliebige Leerzeichen><=>" suchen.

Willst Du die unterschiedlichen Namen in unterschiedlichen Code-Blöcken auseinander halten, so müßtest Du die Datei mit einem Parser parsen und dann die Semantik auswerten. Das ist sicherlich ungleich komplexer!

Hinzu kommt noch die Problematik, dass Du ja nicht nur die Zuweisung ändern müßtest, sondern auch die Stellen, an denen ein Bezeichner als Parameter übergeben wird.

Code: Alles auswählen

int bar = 1;
// hier müßte bar ja auch durch den neuen Namen ersetz werden!
foo(bar);
Was genau planst Du denn? Viele Editoren und IDEs berherrschen das relativ gut. Und simples Suchen / Ersetzen kann man auch mit jedem Editor oder auf Shell-Ebene mit Tools wie "sed".

Verfasst: Freitag 30. Oktober 2009, 17:10
von SigMA

Code: Alles auswählen

tmp = file(DATEINAME, "rb").read().split("\n")
result = ""
for line in tmp:
  line = line.replace(STICHWORT, DURCHWAS_ERSETZEN)
  if line: self.result += line+u"\n"
Öffne Datei,
Gehe durch jede Zeile,
Ersetzte in JEDER Zeile STICHWORT durch DURCHWAS_ERSETZEN,
Wenn Die Zeile nicht leer ist, dann füg wieder hinzu,
Neue Datei in '''result''' muss man dann nur noch schreiben

Q&D aber so sollte es gehen^^

Verfasst: Freitag 30. Oktober 2009, 17:37
von BlackJack
@SigMA: OMG was für ein Murks ist dass denn? Man könne auch Zeilenweise über die Datei iterieren statt sie komplett einzulesen, und dann in eine Liste mit Zeilen zu trennen. Zu dem Zeitpunkt hat man die Daten dann gleich doppelt im Speicher. Zeichenketten mit ``+=`` in einer Schleife "aufaddieren" kann eine besch..., nämlich quadratische Laufzeit haben. Wo kommt das `self` her? Und warum willst Du nur reine ASCII-Dateien bearbeiten, die aber trotzdem in Unicode umwandeln!?

Verfasst: Freitag 30. Oktober 2009, 17:39
von numerix
SigMA hat geschrieben:Q&D aber so sollte es gehen^^
Nein, so geht es ganz sicher nicht.

Verfasst: Freitag 30. Oktober 2009, 18:10
von steffan
Hyperion hat geschrieben: Was genau planst Du denn? Viele Editoren und IDEs berherrschen das relativ gut. Und simples Suchen / Ersetzen kann man auch mit jedem Editor oder auf Shell-Ebene mit Tools wie "sed".
Zuerst beschäftige ich mich nur mit Suchen/Ersetzen. Da werde ich mich jetzt über geeignete Tools informieren.

Hintergrund ist...
Ich will einen Code-Generator schreiben. Der Benutzer soll zwischen meinen Code-Konstrukten wählen, dem Konstrukt einen Namen geben und einige weitere Attribute angeben. Das soll der Benutzer in eine XML-Datei schreiben und anhand dieser wird mein Programm den richtigen Code generieren.

Verfasst: Freitag 30. Oktober 2009, 18:19
von BlackJack
@steffan: Dann möchtest Du vielleicht mal die vielen Template-Bibliotheken für Python anschauen, statt da etwas mit suchen und ersetzen zu basteln.

Das simpelste wäre `string.Template` aus der Standardbibliothek:

Code: Alles auswählen

In [186]: t = string.Template('$name=2*4;')

In [187]: t.substitute(name='Window')
Out[187]: 'Window=2*4;'

Verfasst: Freitag 30. Oktober 2009, 18:21
von ms4py
Wenn du da deine Konstrukte bzw. Templates (oder was auch immer) sinnvoll wählst, reicht da einfaches Suchen und Ersetzen, also

Code: Alles auswählen

str.replace('old', 'new')
Oder besser du nimmst die ``str.format`` Methode (Python >= 2.6):

Code: Alles auswählen

template = 'int {var_name} = 5;'
output = template.format(var_name= 'new_name')
Oder du verwendest die Template-Klasse:
http://docs.python.org/dev/library/stri ... te-strings

Verfasst: Samstag 31. Oktober 2009, 10:36
von sma

Code: Alles auswählen

s = """
int NAME = 4 * 3; // dies wird ersetzt

void bar() {
    int a = 3; // dies nicht
}
"""

import re

replacements = {'NAME': 'Window'}

def f(m): return m.group(1) + replacements[m.group(2)]

print re.sub(r"(?m)^(\w+\s+)(\w+)(?=\s*=)", f, s)
Stefan