Seite 1 von 4

Funktion, die Platzhalter ("*" und "?") in String prüft ?

Verfasst: 22.07.2011 16:00
von c4s
Gibt es einen Code (oder API-Befehl) der einen String mit einem anderen String, der Platzhalter ("*" und "?") enthält, vergleicht und ausgibt ob letzterer String zutrifft?

Bestes Beispiel hierfür ist die Windows-Suche:

Code: Alles auswählen

"*.exe" für Dateien, die auf "exe" enden
"?????.txt" für Texte mit fünfstelligem Dateinamen

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 22.07.2011 16:05
von RSBasic
Das, was du suchst, sind Wildcards: http://www.google.de/#sclient=psy&hl=de ... 80&bih=897

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 22.07.2011 17:05
von STARGÅTE
Am einfachsten wäre es, wenn du es mit Regulären Ausdrücken prüfst.

Ansonsten gibs hier noch n Code von mir mit FindPattern() und ReplacePattern()

Code: Alles auswählen

Structure CharacterArray
	c.c[0]
EndStructure

Global *LowCaseCharacter.CharacterArray = ?LowCaseCharacter

Procedure Pattern_Find(*String.CharacterArray, *Pattern.CharacterArray, *FoundLength.Integer=#Null)
	
	Protected StringIndex.i, PatternIndex.i, FoundLength.i, Position.i
	
	While *String\c[StringIndex]
		Repeat
			While *Pattern\c[PatternIndex]
				Select *Pattern\c[PatternIndex]
					Case '?' ; Platzhalter für genau ein Zeichen
						If *String\c[StringIndex+PatternIndex] = ''
							Break 2
						EndIf
					Case '*' ; Platzhalter für eine beliebige Anzahl von Zeichen (auch keins)
						Position = Pattern_Find(@*String\c[StringIndex], @*Pattern\c[PatternIndex+1], @FoundLength)
						If Not Position
							Break 2
						Else
							FoundLength + Position-PatternIndex-1
							If *Pattern\c[PatternIndex+1] = ''
								While *String\c[StringIndex+FoundLength]
									FoundLength + 1
								Wend
							EndIf
							Break
						EndIf     
					Default ; Beliebiges anderes Zeichen
						If *LowCaseCharacter\c[*String\c[StringIndex+PatternIndex]] <> *LowCaseCharacter\c[*Pattern\c[PatternIndex]]
							Break 2
						EndIf
				EndSelect
				PatternIndex + 1
			Wend
			If *FoundLength
				*FoundLength\i = FoundLength+PatternIndex;+StringIndex
			EndIf
			ProcedureReturn StringIndex+1
		Until #True
		PatternIndex = 0
		StringIndex + 1
	Wend
	
EndProcedure



Procedure FindPattern(String.s, Pattern.s, StartPosition=1, *FoundLength.Integer=#Null)
	
	Protected Result.i, *String.CharacterArray = @String
	
	If Not Pattern
		ProcedureReturn #Null
	ElseIf StartPosition > Len(String)
		ProcedureReturn #Null
	ElseIf StartPosition > 1
		Result = Pattern_Find(@*String\c[StartPosition-1], @Pattern, *FoundLength)
		If Result
			ProcedureReturn Result+StartPosition-1
		Else
			ProcedureReturn #Null
		EndIf
	Else
		ProcedureReturn Pattern_Find(@*String\c[0], @Pattern, *FoundLength)
	EndIf
	
EndProcedure



Procedure.s ReplacePattern(String.s, PatternToFind.s, StringToReplace.s)
	
	Protected Position, FoundLength
	
	Repeat
		FoundLength = 0
		Position = FindPattern(String, PatternToFind, Position, @FoundLength)
		If Position
			String = Left(String, Position-1)+Mid(String, Position+FoundLength)
			If Position > Len(String)
				String + StringToReplace
			Else
				String = InsertString(String, StringToReplace, Position)
			EndIf
			Position + Len(StringToReplace)
		EndIf
	Until Not Position
	
	ProcedureReturn String
	
EndProcedure


DataSection
	LowCaseCharacter:
	Data.c $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F
	Data.c $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E, $1F
	Data.c $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E, $2F
	Data.c $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E, $3F
	Data.c $40, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $6F
	Data.c $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $5B, $5C, $5D, $5E, $5F
	Data.c $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E, $6F
	Data.c $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $7B, $7C, $7D, $7E, $7F
	Data.c $80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $9A, $8B, $9C, $8D, $9E, $8F
	Data.c $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $9E, $FF
	Data.c $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7, $A8, $A9, $AA, $AB, $AC, $AD, $AE, $AF
	Data.c $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7, $B8, $B9, $BA, $BB, $BC, $BD, $BE, $BF
	Data.c $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $EF
	Data.c $F0, $F1, $F2, $F3, $F4, $F5, $F6, $D7, $F8, $F9, $FA, $FB, $FC, $FD, $FE, $DF
	Data.c $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE, $EF
	Data.c $F0, $F1, $F2, $F3, $F4, $F5, $F6, $F7, $F8, $F9, $FA, $FB, $FC, $FD, $FE, $FF
EndDataSection

;- Beispiel


Debug FindPattern("Beispiel.exe", "?ei*.exe")
Debug ReplacePattern("Beispiel.exe", "B*l", "-")

Hinweis: Groß-Klein-Schreibung wird ignoriert

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 22.07.2011 17:14
von c4s
@RSBasic
Leider findet sich jedoch nichts, wo auch "?" unterstützt wird.


@STARGÅTE
Das sieht nach genau dem aus, was ich brauche. Danke!

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 22.07.2011 17:20
von RSBasic
Joar mit RegEx kann man das auch machen.

@c4s
Dann hast du aber nicht gründlich gesucht <) : http://www.purebasic.fr/english/viewtop ... 269#p41269 (1. Treffer, 4. Beitrag)

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 22.07.2011 18:10
von c4s
RSBasic hat geschrieben:@c4s
Dann hast du aber nicht gründlich gesucht <) : http://www.purebasic.fr/english/viewtop ... 269#p41269 (1. Treffer, 4. Beitrag)
Du hast mich ertappt. :lol:

Da ist tatsächliche so einiges initeressantes dabei. Muss ich mir demnächst mal genauer anschauen.

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 24.07.2011 12:52
von sibru
Uralt, aber funktionsfähiger PB-Code:

Code: Alles auswählen

;+----------------------------------------------------------------------+
;|           PureBasic-QuellCode "match" mit allen ModulBody´s          |
;|erstellt durch Programm "PB_Mod2Body", Vers. 11225a am 24.07.11, 12:49|
;+----------------------------------------------------------------------+


;Modul      match Version 1.0 vom 25.01.2005
#PB_Vers  = "4.20"
;
;Funktion:  prüft einen Text gegen eine Text-Maske
;
;Aufruf:    passt.b = match(Text$, TextMaske$) - prüft einen Text gegen eine Text-Maske
;           liefert 1, wenn Text$ der TextMaske$ entspricht,
;           ansonsten 0
;           TextMaske$ kann folgende Joker enthalten:
;           ? --> an dieser Stelle kann irgendein Zeichen stehen
;           # --> an dieser Stelle muss ein Zeichen 0..9 stehen
;           * --> ab dieser Stelle wird nicht mehr verglichen.
;
;

 ;==========  Begin Modul "C:\AlsterSoft\PureBasic\PB4.20\Module\max.PBI"  ==========
#PB_Vers  = "4.20"
Procedure Max(w1,w2)
  If w1>w2 
    ProcedureReturn w1 
  EndIf
  ProcedureReturn w2
EndProcedure
 ;==========  Ende Modul "C:\AlsterSoft\PureBasic\PB4.20\Module\max.PBI"  ==========
 ;==========  Begin Modul "C:\AlsterSoft\PureBasic\PB4.20\Module\nbr.PBI"  ==========
#PB_Vers  = "4.20"
 ;==========  Begin Modul "C:\AlsterSoft\PureBasic\PB4.20\Module\SGN.PBI"  ==========
#PB_Vers  = "4.20"
Procedure.b SGN(Wert.l)
  If Wert<0
    ProcedureReturn -1
  ElseIf Wert>0
    ProcedureReturn 1
  Else
    ProcedureReturn 0
  EndIf
EndProcedure
 ;==========  Ende Modul "C:\AlsterSoft\PureBasic\PB4.20\Module\SGN.PBI"  ==========
Procedure.b nbr(String$)
   Protected i, nbr, c$, Komma
   i = 1
   nbr = SGN(Len(String$))
   While i< = Len(String$) And nbr>0
      c$ = Mid(String$, i, 1)
      nbr = FindString("0123456789.-", c$, 1)
      i = i + 1
      If c$ = "-" And i>2  
        ProcedureReturn 0
      ElseIf c$ = "."  
        If Komma : ProcedureReturn 0
        Else : Komma = 1
        EndIf
      EndIf
   Wend
   ProcedureReturn SGN(nbr)
EndProcedure
 ;==========  Ende Modul "C:\AlsterSoft\PureBasic\PB4.20\Module\nbr.PBI"  ==========
Procedure.b match(String$,mask$)
Protected ChkPos.l, ChkLen.l, ok.b, StrChar$, MskChar$
   ChkLen.l=max(Len(String$),Len(mask$))
   ChkPos.l=1
   ok.b=1
   While ChkPos<=ChkLen And ok
      StrChar$=Mid(String$,ChkPos,1)
      MskChar$=Mid(mask$,ChkPos,1)
      If MskChar$="?" Or (MskChar$="#" And nbr(StrChar$)) Or MskChar$=StrChar$
         ChkPos+1
      ElseIf MskChar$="*"
         ChkPos=ChkLen+1
      Else
         ok=0
      EndIf
   Wend
   ProcedureReturn ok
EndProcedure


;==========< Auswertung >==========
;      111 Zeilen
;     3292 Bytes
;        3 Module


Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 24.07.2011 13:55
von c4s
@sibru
Funktioniert aber nicht wie gewollt bzw. gewohnt. So sollte z.B. "*.*" bei "testexe" 0 ergeben (da der Punkt nicht vorhanden ist). Einfach abbrechen ist also für meinen Zweck nicht verwendbar.

Die Idee mit "#" um speziell Zahlen zu testen finde ich aber sehr gut![/code]

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 24.07.2011 22:13
von c4s
Mit RegEx kenne ich mich eigentlich gar nicht aus, aber dennoch die Frage:
Wie könnte man das mit RegEx umsetzen? (Also "?", "*" und eventuell "#" für Ziffern)

@STARGÅTE
Bei deinem Code blicke ich auch nicht ganz durch. ;)
Funktioniert er auch mit Unicode? Wozu das globale LowCaseCharacter-Array, wegen dem rekursiven Aufruf?

Re: Funktion, die Platzhalter ("*" und "?") in String prüft

Verfasst: 24.07.2011 22:37
von STARGÅTE
Da du vermutlich weiterhin die ? * # nutezn willst, musst du es noch konvertieren:

Code: Alles auswählen


Procedure.s QuoteRegularExpression(String.s)
	Protected Character.s
	Restore RegularExpressionQuoteCharacters
	Read.s Character
	While Character
		String = ReplaceString(String, Character, "\"+Character)
		Read.s Character
	Wend
	ProcedureReturn String
EndProcedure

Procedure MatchPattern(String.s, Pattern.s)
	Protected Reg.i
	Pattern = QuoteRegularExpression(LCase(Pattern))
	Pattern = ReplaceString(Pattern, "\?", ".")
	Pattern = ReplaceString(Pattern, "\*", ".*")
	Pattern = ReplaceString(Pattern, "#", "\d")
	Reg = CreateRegularExpression(#PB_Any, Pattern, #PB_RegularExpression_DotAll)
	ProcedureReturn MatchRegularExpression(Reg, LCase(String)) 
EndProcedure

DataSection
	RegularExpressionQuoteCharacters:
	Data.s "\", ".", "+", "*", "?", "[", "^", "]", "$", "(", ")"
	Data.s "{", "}", "=", "!", "<", ">", "|", ":", "-", ""
EndDataSection

Debug MatchPattern("Test", "t*#.???")
Debug MatchPattern("Test.ex", "t*#.???")
Debug MatchPattern("Test.exe", "t*#.???")
Debug MatchPattern("Test1.exe", "t*#.???")
Obwohl bei der ganzen String-Jongliererei mein Code mit sicherheit schneller wäre ^^
Wenn du es brauchst kann ich dir das noch einbauen ...
Für was genau brauchst du es eigentlich, dann kann man ja den Code vielleicht noch optimieren