Optimierte Stringoperationen mit Platzhaltern (ähnlich TC)

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Ghosty1967
Beiträge: 203
Registriert: 29.08.2005 13:56
Computerausstattung: Intel i7, 128GB Ram, Win10 Ultimate, PB6.00 Alpha 3
Wohnort: Köln

Optimierte Stringoperationen mit Platzhaltern (ähnlich TC)

Beitrag von Ghosty1967 »

Hallo PB-Gemeinde...
Ich arbeite gerade aus Spass an der Freud' an einem "Umbenenner" für Dateinamen wie er ähnlich auch im TotalCommander mit dem
"Mehrfach-Umbenenn-Tool" realisiert ist. Die Idee entstand, da ich in diesem Modul vielerlei Möglichkeiten der "Manipulation" vermisst
habe. Ein grober Rahmen existiert schon und funktioniert soweit auch - ist allerdings nur reines "Studien-Programm" ohne große
Struktur und noch mit jedermenge Fehlerchen.
Ich mache mir jedoch jetzt schon Gedanken bezüglich der Performance und dachte, ihr könntet mir bei der Optimierung einiger
Proceduren / Funktionen helfen. Eine der wichtigsten Funktionen wäre da das Ersetzen von Platzhalter, die der Benutzer vorgibt.
Beispiel:
Aus dem Dateinamen
"Frank Zappa - You Are What You Is - Society Pages.mp3"
wir mittels der vorgegebenen Maske
"[N7-11], [N-5][N12-]"
der neue Dateiname
"Zappa, Frank - You Are What You Is - Society Pages.mp3"
...[N7-11] = "Zappa"
...[N-5] = "Frank"
...[N12-] = "You Are What You Is - Society Pages.mp3"
Im Moment sieht meine vorläufige Lösung folgendermaßen aus...

Code: Alles auswählen

dateiname.s = "Frank Zappa - You Are What You Is - Society Pages.mp3"
usermaske.s = "[N7-11], [N1-5][N12-]"

;Schleife durchlaufen, solange der Platzhalter "[N" vorhanden ist
While FindString(usermaske, "[N") And FindString(usermaske, "]")
  ;Prüfen, ob ein Start- bzw. Endwert angegeben ist
  pStart.l = FindString(usermaske, "[N", 1) + 2
  pEnde.l  = FindString(usermaske, "]" , pStart - 1)
  platzhalter.s = Mid(usermaske, pStart, (pEnde - pStart))
  ;Wenn ein "-" im Platzhalter vorhanden ist, Start und Endwert holen
  If FindString(platzhalter, "-")
    ;Integerwert vor dem "-" holen 
    first.l = Val(Left(platzhalter, FindString(platzhalter, "-") - 1))
    ;Integerwert nach dem "-" holen 
    last.l  = Val(Mid (platzhalter, FindString(platzhalter, "-") + 1))
    ;Wenn der ;Integerwert vor dem "-" = 0 (keine Zahl, z.B. [N-5]) ist, diesen auf 1 setzen
    If first = 0: first = 1: EndIf
    ;Wenn der ;Integerwert nach dem "-" = 0 (keine Zahl, z.B. [5-]) ist, diesen auf unendlich setzen
    If last  = 0: last = 9999: EndIf
    ersetze.s = Mid(dateiname, first, (last-first) + 1)
  Else
    ;Wenn keine Start und Endwerte angegeben sind, den kompletten Namen zuweisen
    ersetze = dateiname
  EndIf
  ;den zu aktuellen Platzhalterin der Usermaske ersetzen mit dem ermittelten Teilstring
  usermaske = ReplaceString(usermaske, "[N" + platzhalter + "]", ersetze, #PB_String_CaseSensitive, 1, 1)
Wend

Debug "aus"  + #TAB$ + dateiname
Debug "wird" + #TAB$ + usermaske
Ich glaube, hier liegt Verbesserungs- bzw. Optimierungspotential. Vielleicht hat jemand von Euch Lust daran rumzubasteln
und seine Ideen mit mir zu teilen...
Ich wünsche allen natürlich auch noch einen "Guten Rutsch" ins neue Jahr!
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Optimierte Stringoperationen mit Platzhaltern (ähnlich T

Beitrag von STARGÅTE »

Hallo Ghosty1967,

sowas kannst/solltest du mit regulären Ausdrücken machen.
In dem regulären Ausdruck kannst das Format angeben und er gibt dir immer die passenden Felder.
Hier ein Beispiel wie ich das meine:

Code: Alles auswählen

Enumeration
	#RegularExpression
EndEnumeration

Procedure ParseFileName(FileName.s)
	
	If ExamineRegularExpression(#RegularExpression, FileName)
		While NextRegularExpressionMatch(#RegularExpression)
			Debug "FirstName = " + RegularExpressionNamedGroup(#RegularExpression, "FirstName")
			Debug "LastName  = " + RegularExpressionNamedGroup(#RegularExpression, "LastName")
			Debug "Title     = " + RegularExpressionNamedGroup(#RegularExpression, "Title")
			Debug "Band      = " + RegularExpressionNamedGroup(#RegularExpression, "Band")
			Debug "----"
		Wend
	EndIf
	
EndProcedure

Define Syntax.s

Syntax = "(?P<FirstName>\w+) \s+ (?P<LastName>\w+) \s*-\s* (?P<Title>[\w\s]+?) \s*-\s* (?P<Band>[\w\s]+?) \.\w+"

If CreateRegularExpression(#RegularExpression, Syntax, #PB_RegularExpression_Extended)
	ParseFileName("Frank Zappa - You Are What You Is - Society Pages.mp3")
Else
	Debug RegularExpressionError()
EndIf
Danach kannst du anhand der Felder den Dateinamen erstellen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Ghosty1967
Beiträge: 203
Registriert: 29.08.2005 13:56
Computerausstattung: Intel i7, 128GB Ram, Win10 Ultimate, PB6.00 Alpha 3
Wohnort: Köln

Re: Optimierte Stringoperationen mit Platzhaltern (ähnlich T

Beitrag von Ghosty1967 »

Hallo STARGÅTE...
Danke für deinen sehr interessanten Vorschlag. "RegularExpression" war mir bisher gar kein Begriff im Zusammenhang mit PB.
Allerdings finde ich die Syntax recht kompliziert. Es geht mir nicht darum, Dateinamen immer nach einem bestimmten Muster
zu zerlegen, sondern vielmehr darum, angeben zu können, WIE ein Dateiname gebildet werden soll. Die "Platzhalter" sollen
ja nur bestimmte Funktionen aufrufen, welche den Namen neu zusammensetzen bzw. Teile hinzufügen, löschen oder ersetzen.
Es gibt noch weitere Platzhalter die ähnliche Funktionen ausführen wie z.B.

[N] bzw. [N#-#] für das Einfügen des Originalnamens oder eines angegebenen Teils des Originalnames
[P] bzw. [P#-#] für das Einfügen der Dateierweiterung oder eines angegebenen Teils der Dateierweiterung
[C] für das Einfügen eines definierten Zählers (Start, Schrittweite, Länge)
[R] für das Einfügen eines definierten Zufallszahlgenerators (Min, Max, Länge)
[D] bzw. [Dddmmyyyy] für das Einfügen des Systemdatums inkl. definierbarer Datumsmaske
[T] bzw. [Thhmmss] für das Einfügen der Systemzeit inkl. definierbarer Zeitmaske
[E] bzw. [E#-#] fügt eine Zeile eines Textes aus einem Editorgadget ein
bzw. [U#-#] Konvertiert den angegebenen Teil in Großbuchstaben
[L] bzw. [L#-#] Konvertiert den angegebenen Teil in Kleinbuchstaben

wären diese "Token" auch mittels "RegularExpression" bearbeitbar und wenn ja, wie würde man soetwas angehen, da es sich ja
meist nicht um Felder mit fest definierten Längen oder Inhalten handelt :allright:
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Optimierte Stringoperationen mit Platzhaltern (ähnlich T

Beitrag von STARGÅTE »

RegularExpressions sind zum lesen von Zeichenketten gedacht die nicht immer die exakt selbe Form haben, aber bestimmte Muster.
Du willst ja anscheinend immer exakten Positionen aus dem Dateinamen extrahieren.
Dann wäre das normale Mid() von PureBasic natürlich ausreichend.

Was du aber mit RegularExpressions machen kannst, ist "dein" Syntax einfach zu parsen:
Anstelle der Debugausgabe kannst du an diesen Stellen dann den Dateinamen mit Mid() lesen und zusammen bauen.

Code: Alles auswählen

Enumeration
	#RegularExpression
EndEnumeration

Procedure ParseFileName(FileName.s)
	
	If ExamineRegularExpression(#RegularExpression, FileName)
		While NextRegularExpressionMatch(#RegularExpression)
			If RegularExpressionNamedGroup(#RegularExpression, "NameStart")
				Debug "NameStart = " + RegularExpressionNamedGroup(#RegularExpression, "NameStart") + " , NameEnd  = " + RegularExpressionNamedGroup(#RegularExpression, "NameEnd")
			EndIf
			If RegularExpressionNamedGroup(#RegularExpression, "UpperStart")
				Debug "UpperStart = " + RegularExpressionNamedGroup(#RegularExpression, "UpperStart") + " , UpperEnd  = " + RegularExpressionNamedGroup(#RegularExpression, "UpperEnd")
			EndIf
			If RegularExpressionNamedGroup(#RegularExpression, "Other")
				Debug "Other = " + RegularExpressionNamedGroup(#RegularExpression, "Other")
			EndIf
		Wend
	EndIf
	
EndProcedure

Define Syntax.s

Syntax = "\[N(?P<NameStart>\d*)-(?P<NameEnd>\d*)\] | \[U(?P<UpperStart>\d*)-(?P<UpperEnd>\d*)\] | (?P<Other>.*?(?=\[))"

If CreateRegularExpression(#RegularExpression, Syntax, #PB_RegularExpression_Extended)
	ParseFileName("[N7-11], [U1-5][N12-]")
Else
	Debug RegularExpressionError()
EndIf
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Ghosty1967
Beiträge: 203
Registriert: 29.08.2005 13:56
Computerausstattung: Intel i7, 128GB Ram, Win10 Ultimate, PB6.00 Alpha 3
Wohnort: Köln

Re: Optimierte Stringoperationen mit Platzhaltern (ähnlich T

Beitrag von Ghosty1967 »

Das klingt sehr interessant...
dein Beispiel scheint mir da wirklich weiterzuhelfen. Ich bastel damit mal ein bisschen rum und werde meine Lösung posten.

Danke dir!
Michael Vogel
Beiträge: 71
Registriert: 16.03.2006 11:20

Re: Optimierte Stringoperationen mit Platzhaltern (ähnlich T

Beitrag von Michael Vogel »

Hab schon 'mal etwas ähnliches gebastelt, vielleicht passt das ja bereits für dich (siehe hier...
...oder es liefert dir ein paar Ideen, wie man es nicht machen sollte :lol:

Ich hab das ganze mit regulären Ausdrücken gemacht, allerdings (würde ich jetzt nicht mehr so machen) zum Gruppieren die Zeichen '<' und '>' anstelle von Klammern genommen. Der Gedanke war, dass diese Zeichen in Dateinamen nicht vorkommenr - aber irgendwie fühlt sich das doch etwas ungewohnt an (aber man kann damit leben)...

Für dein Beispiel bräuchte es die Ausdrücke "<.*?>< -><.*?><-><.*>" und "<n3>, <n1><n4><n5>.<e>"
Antworten