Seite 1 von 2

ReplaceString nur so und so oft mal (wie bei RemoveString) ?

Verfasst: 17.08.2010 00:58
von padawan
Guten Abend,

ich suche eine Möglichkeit, nicht alle Vorkommen eines Substrings in einem String durch einen Ersatzstring zu ersetzen, sondern nur eine bestimmte Anzahl von Vorkommen. Gibt es dafür schon einen Workaround - oder wie würdet ihr das angehen? Also, als Beispiel, im String "Jeder.muss.mal.abtreten. Schade!" will ich alle Punkte durch ein Leerzeichen ersetzen, außer dem letzten Punkt nach "abtreten", der soll bleiben.

Grüße, padawan

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 01:18
von TomS
Wenn du N Zeichen(ketten) ersetzen willst, musst du wohl zählen.
Falls du immer nur den letzten Punkt behalten möchtest suchst du mit FindString das letzte Vorkommen und splittest an dieser Stelle. Dann ersetzt du im ersten Teil alles und fügst die beiden Teile wieder mit einem Punkt dazwischen zusammen.

Code: Alles auswählen

Procedure.s Replace(string.s, find.s, replace.s, separator.s)
	Protected findstringpos.i
	Protected part1.s
	Protected part2.s
	
	While FindString(string, find, findstringpos)
		findstringpos = FindString(string, find, findstringpos)+1
	Wend 

	part1 = Left(string, findstringpos-2 )
	part1 = ReplaceString(part1, find, replace)
	part2 = Right(string, Len(string)-findstringpos+1)
	ProcedureReturn part1 + separator + part2
EndProcedure 

Debug Replace("a.b.c.d.txt", ".", " ", ".")
Debug Replace("Jeder.muss.mal.abtreten. Schade!", ".", " ", ".")
Debug Replace("Jeder.muss.mal.abtreten. Schade!", ".", " ", ". Das ist")

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 01:22
von STARGÅTE
Dafür würde sich ein Regulärer Ausdruck eignen:

Code: Alles auswählen

#RegularExpression = 1

If CreateRegularExpression(#RegularExpression, "\.(?=.*\.)")
 
  String$ = "Jeder.muss.mal.abtreten. Schade!"
  
  NewString$ = ReplaceRegularExpression(#RegularExpression, String$, " ")
  
  Debug NewString$

EndIf
oder du zerlegst die Zeichenkette mit StringField() bei jedem Punkt, und baust sie dann mit Leerzeichen wieder zusammen, bis zum vorletzten, dann ein Punkt und das Letze. (ähnlich wie mein vorposter)

oder du arbeitest direkt im Speicher und gehst den String von hinten nach vorne durch und killst alle Punkte nach dem ersten:

Code: Alles auswählen

Procedure Test(*Character.Character)
  Protected *Position.Character = *Character + MemoryStringLength(*Character)
  Protected Kill
  While *Position >= *Character
    If *Position\c = '.'
      If Kill : *Position\c = ' ' : EndIf
      Kill = #True
    EndIf
    *Position - SizeOf(Character)
  Wend
EndProcedure

String$ = "Jeder.muss.mal.abtreten. Schade!" 
Test(@String$)
Debug String$
die direkte Variante im Speicher ist wohl das schnellste, da es ohne Temporäre Strings arbeitet!

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 01:23
von Kiffi
hier 'meiner' (Original von superadnim):

Code: Alles auswählen

Procedure.s StringReplace( szStr.s, szStrSrc.s, szStrRepl.s, dwTimes=1 )
  
  Protected dwPos, i
  
  For i=1 To dwTimes
    dwPos   = FindString(szStr, szStrSrc, 1)
    If  dwPos
      szStr = Left(szStr, dwPos-1) + szStrRepl + Right(szStr, (Len(szStr)-dwPos-Len(szStrSrc)+1) )
    Else
      Break
    EndIf
  Next
  
  ProcedureReturn szStr
  
EndProcedure

myString.s = "1.2.3.4.5"

Debug StringReplace("1.2.3.4.5", ".", " ", CountString(myString, ".") - 1)

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 01:52
von padawan
Ui - schon ne Menge gute Vorschläge, vielen Dank! Ich arbeite das mal ab und melde mich a.s.a.p zurück!

Grüße, padawan

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 07:35
von hjbremer
im Prinzip wie Stargates Vorschlag, nur etwas anders

Code: Alles auswählen

Structure charArray
   c.c[0]
EndStructure

Procedure.s Test1(x$)

   Protected j, k, *c.charArray = @x$
   
   Repeat
      If *c\c[j] = '.'
         *c\c[j] = ' '
         k = j
      EndIf      
      j + 1   
   Until Not *c\c[j] 
   
   If k: *c\c[k] = '.': EndIf
   
   ProcedureReturn x$
EndProcedure

String$ = "Jeder.muss.mal.abtreten. Schade!" 

string$ = Test1(string$)

Debug String$

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 22:43
von padawan
Die sind alle cool, die Lösungen :allright: vielen Dank für euer Input. Für mich persönlich ist die Lösung von Stargate mit dem Regulären Ausdruck am reizvollsten, weil ich sowieso gerade versuche, mich mit dem Thema anzufreunden. Diesen Ausdruck kann ich mir jetzt mal richtig genüsslich auf der Zunge zergehen lassen.

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 22:55
von STARGÅTE
JO, aber Reguläre Ausdrücke sind trotzdem mit vorsicht zu genießen.
Es ist nicht immer gesagt das diese am schnellsten sind ...

"\.(?=.*\.)" bedeutet in worten: Suche nach einem Punkt "\.", nachdem "(?=)" eine unbestimmte lange Zeichenfolge ".*" kommt, und wiederum ein Punkt enthält "\." ...

Beachte bitte noch:
Wichtig: Die PCRE Lizenz erfordert, dass eine Copyright-Notiz und der Lizenz-Text selbst in jede Software integriert werden, welche die Bibliothek beinhaltet. Wenn also die Bibliothek in einer Software verwendet wird, welche öffentlich zugänglich gemacht wird, dann MUSS die oben verlinkte Lizenz in die Software integriert werden.

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 23:20
von padawan
Danke für die Erklärung im Detail, Stargate. Ist schon extrem komprimiert, soviel Logik auf so wenige Zeichen. Kannst du eine gute Einführung in das Thema empfehlen? Ich meine, man kann das zwar alles unter http://www.pcre.org/pcre.txt nachlesen, aber das ist nicht gerade, was ich unter einer guten Einführung verstehe... ist ja auch nicht als solche gedacht.

Danke auch für den Hinweis mit der Lizenz.

Grüße, padawan

Re: ReplaceString nur so und so oft mal (wie bei RemoveStrin

Verfasst: 17.08.2010 23:25
von STARGÅTE
Ich habe das hier genutzt:
RegExp-Tutorial

Ist zwar eigentlich für PHP gedacht, trotzdem sind die meisten Sachen identisch mit PB ...