Seite 1 von 2

Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 18:15
von blastar
Hallo,

ich habe da mal eine Frage zu 'ReplaceString()'.
Nachdem der 'ReplacementString$' im 'String$ ' eingefuegt wurde, wird dieser leider nicht mehr fuer nachfolgende Checks beachtet.

hier mal ein schnelles Beispiel mit '0':

Code: Alles auswählen

string.s = "0000000000"
string   = ReplaceString(string, "00", "0")
Debug string ; = 00000
Das sollte im idealen Fall (so stelle ich mir das vor) eine einzelne '0' ausgeben... leider gibt das '00000' aus. Ist das korrekt so (getestet unter 4.62 - 5.60) oder muss ich dazu einen anderen Befehl nutzen?

Hintergrund: ich habe ein Log-Datei welche ich auslesen will. Die tabellenartige Formatierung ist durch das x-fache einfuegen von Space-zeichen erfolgt. Um den Befehl 'StringField()' gezielt zu nutzen muss ich aber erstmal alle sich wiederholenden Space-zeichen durch ein einziges ersetzen. Im Moment nutze ich den Umweg 'ReplaceString()' mehrfach aufzurufen... gib es da eine einfachere Loesung?

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 18:48
von NicTheQuick
Hab grad was dafür gebastelt. Vorsicht: Wildes Gepointere! :-D

Code: Alles auswählen

Procedure.s MyStringField(*string, index.i, separator.s)
	Protected *sep.Character = @separator
	Protected *c.Character = *string, *begin
	
	While *c\c And *c\c = *sep\c
		*c + SizeOf(Character)
	Wend
	
	*begin = *c
	While *c\c
		If *c\c = *sep\c
			index - 1
			If index = 0
				ProcedureReturn PeekS(*begin, (*c - *begin) / SizeOf(Character))
			EndIf
			While *c\c And *c\c = *sep\c
				*c + SizeOf(Character)
			Wend
			*begin = *c
			Continue
		EndIf
		
		*c + SizeOf(Character)
	Wend
	If index = 1
		ProcedureReturn PeekS(*begin, (*c - *begin) / SizeOf(Character))
	Else
		ProcedureReturn ""
	EndIf
EndProcedure

zeile.s = "   Spalte1       Spalte2        Spalte3"

Debug MyStringField(@zeile, 1, " ")
Debug MyStringField(@zeile, 2, " ")
Debug MyStringField(@zeile, 3, " ")

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 19:06
von Sicro

Code: Alles auswählen

; --------------------------------------
; Beim Programmstart

; \S bedeutet: Alles außer Leerzeichen
; *  bedeutet: beliebige Anzahl, auch keines Mal
; \s bedeutet: Leerzeichen
; +  bedeutet: Es muss mindestens einmal vorkommen
; () bedeutet: Gruppierung

RegEx = CreateRegularExpression(#PB_Any, "\s*(\S*)\s+(\S*)\s+(\S*)\s+(\S*)\s*")
If Not RegEx
  Debug "Fehler: CreateRegularExpression"
  End
EndIf
; --------------------------------------



TabellenZeile$ = "  bla1      bla2    bla3  bla4    "

If ExamineRegularExpression(RegEx, TabellenZeile$) And NextRegularExpressionMatch(RegEx)
  Debug RegularExpressionGroup(RegEx, 1) + " " +
        RegularExpressionGroup(RegEx, 2) + " " +
        RegularExpressionGroup(RegEx, 3) + " " +
        RegularExpressionGroup(RegEx, 4)
EndIf



; Wenn der beim Programmstart erstellte RegEx nicht mehr benötigt wird,
; diesen freigeben. Beim Programmende wird dieser automatisch freigegeben.
FreeRegularExpression(RegEx)
Edit:
Bezüglich ReplaceString(): Dieser Befehl geht nicht Zeichen für Zeichen durch den String, sondern springt entsprechend der Länge von ErsetzString weiter.

Code: Alles auswählen

00  00  00  00  00
 0   0   0   0   0

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 19:21
von Josh
Dann mach ich bei der Bastelstunde auch mal mit :mrgreen:

Code: Alles auswählen

Structure CHARARRAY
  c.c[0]
EndStructure


Procedure.s EliminateDoubleSpaces (String$)
  Define *Read .CHARARRAY  = @String$
  Define *Write.CHARARRAY  = @String$

  While *Read\c <> 0
    If *Read\c[0] = ' ' And *Read\c[1] = ' '
      *Read + SizeOf(Character)
    Else
      *Write\c = *Read\c
      *Read  + SizeOf(Character)
      *Write + SizeOf(Character)
    EndIf
  Wend
  *Write\c = 0

  ProcedureReturn String$

EndProcedure

Debug "*" + EliminateDoubleSpaces ("    Pure     Basic    ") + "*"

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 19:43
von juergenkulow
Hallo blastar,

Code: Alles auswählen

Declare.s ErsetzeMehrfachZeichen(string.s,Zeichen.s)
string.s = "0000000000LOG-TEXT"
; string   = ReplaceString(string, "00", "0") : Debug string ; 00000LOG-TEXT
string = ErsetzeMehrfachZeichen(string,"0")  : Debug string ; 0LOG-TEXT
string= Space(50)+"         Log-Text 2" :  Debug ErsetzeMehrfachZeichen(string," ") ;  Log-Text 2 
string= "    Log Text 3" :  Debug ErsetzeMehrfachZeichen(string," ")                ;  Log Text 3
string=Space(50)+"   Log Text 4"+ Space(50)+"   Teil 2" :  Debug ErsetzeMehrfachZeichen(string," ") ;  Log Text 4 Teil 2 

Procedure.s ErsetzeMehrfachZeichen(string.s,Zeichen.s)                ; Procedure übernimmt den String und das Leerzeichen oder Nullzeichen und gibt einen String als Ergbenis zurück.
  Protected PositionDoppelZeichen=FindString(string,Zeichen+Zeichen)  ; Es wird die erste Postion im String ermittelt, wo das Zeichen doppelt vorkommt, sonst Null. 
  While PositionDoppelZeichen                                         ; Wiederhole solange Zeichen doppelt vorkommen. 
    string=Left(string,PositionDoppelZeichen-1)+Zeichen+LTrim(Mid(string,PositionDoppelZeichen),Zeichen) ; Füge den neuen String aus dem linken Teil, der beim erstenmal leer ist,
                                                                      ; einmalig das ersetzte Zeichen und dem rechten Teil des Strings jedoch ohne die führenden ersetzten Zeichen zusammen. 
    PositionDoppelZeichen=FindString(string,Zeichen+Zeichen)          ; Finde die nächste Position im String, wo das Zeichen doppelt vorkommt, sonst Null 
  Wend ; while  PositionDoppelZeichen                                                              
  ProcedureReturn string                                              ; Ergebnis angeben.
EndProcedure 

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 20:17
von Kiffi

Code: Alles auswählen

Define OldString.s 
Define String.s = "0000000000"

Repeat
  OldString = String
  String = ReplaceString(String, "00", "0")
Until String = Oldstring

Debug String
Grüße ... Peter

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 21:54
von blastar
Danke fuer die schnellen und umfangreichen Antworten! :allright: Da waren ja schon echt heftigen Loesungen dabei! :o

Das einlesen der Datein erfolgt im Hintergrund per Threading, sind Pointer sicher oder muss ich da noch zusaetzlich was beachten?
Die Loesung mit 'CreateRegularExpression' ist interessant, ich wusste garnicht das es sowas gibt in PB, hat das Nachteile oder gibt es Wechselwirkungen?
Die Ansatze mit 'Bordmitteln' haben auch was... zwar nicht die schnellsten aber am einfachsten zu lesen.

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 23:27
von GPI
Sicro hat geschrieben:Edit:
Bezüglich ReplaceString(): Dieser Befehl geht nicht Zeichen für Zeichen durch den String, sondern springt entsprechend der Länge von ErsetzString weiter.
Was auch Sinn macht, weil ansonsten man leicht eine Endlosschleife bauen kann.

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 23:33
von #NULL
blastar hat geschrieben:Im Moment nutze ich den Umweg 'ReplaceString()' mehrfach aufzurufen... gib es da eine einfachere Loesung?
das is doch schon einfach

Code: Alles auswählen

string.s = "0000000000_0_000_00"
While FindString(string, "00")
  string   = ReplaceString(string, "00", "0")
Wend
Debug string
oder mit regex

Code: Alles auswählen

Define s.s = "00_0000000000000_00000_00_0"
Define n = 0
Repeat
  Dim match.s(0)
  If CreateRegularExpression(0, "0{2,}") ; (two or more zeros)
    n = ExtractRegularExpression(0,s,match())
    If n
      s = ReplaceString(s, match(i), "0") ; (replace repeated zeros with a single one)
    EndIf
  ;Else
  ;  Debug RegularExpressionError()
  EndIf
  ;Debug s
Until Not n
Debug s

Re: Frage zu 'ReplaceString()'

Verfasst: 17.03.2017 23:37
von Sicro
blastar hat geschrieben:Das einlesen der Datein erfolgt im Hintergrund per Threading, sind Pointer sicher oder muss ich da noch zusaetzlich was beachten?
Solange der Thread die Daten verarbeitet, sollten die Daten nicht verändert werden.
blastar hat geschrieben:Die Loesung mit 'CreateRegularExpression' ist interessant, ich wusste garnicht das es sowas gibt in PB, hat das Nachteile oder gibt es Wechselwirkungen?
CreateRegularExpression ist im offiziellem Befehlssatz von PB seit Version 4.20 (23. Mai 2008) enthalten. Die Unterstützung von Gruppierungen gibt es seit PB-Version 5.30 (23. Juli 2014).
Mit regulären Ausdrücken lassen sich Daten von Datenansammlungen recht einfach extrahieren.
Wenn es dir sehr um Geschwindigkeit geht, dann ist eine für deine Aufgabe individuell erstellte und optimierte Lösung besser.

Du solltest dir mal die PB-Hilfe durchschauen. Möglicherweise sind dir noch weitere interessante Befehle unbekannt.