XbPCRE: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
Georg (Diskussion | Beiträge) |
Georg (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
Zeile 531: | Zeile 531: | ||
RETURN (.T.) | RETURN (.T.) | ||
</code> | </code> | ||
== Download == | |||
Von der [http://alaska-software.com/download/showSection.cxp?section=400 Alaska Website] |
Aktuelle Version vom 5. September 2013, 13:38 Uhr
XbPCRE - eine Pearl Compatible Regular Expression Library
PCRE ist eine frei verfügbare DLL, die mit Pearl kompatible Regular Expressions zur Verfügung stellt.
Während Xbase nur ein Standard-Matching bereit stellt, d.h. nur Vergleiche auf einer 1:1 Basis ermöglicht, muss man wenn es um Pattern (Muster, wie bei der Verwendung von Wildcards) geht, entweder die Segel streichen oder PCRE oder eine andere Bibliothek verwenden.
Syntax und Übersichten
Sind in der XbPCRE-Hilfe enthalten und werden hier nicht wiederholt.
Beispielprogramm
Das folgende Programm stellt quasi eine Workbench zur Verfügung, in der man das Verhalten von Regular Expressions ausprobieren kann. Der erste Teil ergibt die AppSys.prg, und der zweite Teil das eigentliche Programm.
#INCLUDE "AppEvent.CH"
#INCLUDE "NLS.CH"
#INCLUDE "Xbp.CH"
FUNCTION AppSys()
Local aSize, oDlg, aPos[2], aSizeNew[2], nI
aSize := AppDesktop():currentSize()
FOR nI := 1 TO 2
aSizeNew[nI] := Int(aSize[nI] * 0.6)
NEXT
IF aSizeNew[1] < 800
aSizeNew[1] := 800
ENDIF
IF aSizeNew[2] < 600
aSizeNew[2] := 600
ENDIF
aPos[1] := Int((aSize[1] - aSizeNew[1]) / 2)
aPos[2] := Int((aSize[2] - aSizeNew[2]) / 2)
oDlg := XbpDialog():new(AppDesktop(), AppDesktop(), aPos, aSizeNew, , .F.)
oDlg:sysmenu := .T.
oDlg:hideButton := .T.
oDlg:taskList := .T.
oDlg:close := {|| CleanUpAfter(), WinManKill(), _QUIT()}
oDlg:title := ""
// oDlg:icon := 2001
oDlg:create()
RootWindow(oDlg)
oDlg:setTitle(GetProgramTitle())
oDlg:drawingArea:scrollBars := XBP_SCROLLBAR_VERT
oDlg:show()
SetAppWindow(oDlg)
RETURN (.T.)
FUNCTION RootWindow(oDlg)
Static oStatic
IF oDlg <> NIL
oStatic := oDlg
ENDIF
IF oStatic = NIL
ConfirmBox(, "Fehler", "Programm nicht richtig geladen", XBPMB_CRITICAL, XBPMB_OK)
QUIT
ENDIF
RETURN (oStatic)
#DEFINE ENTRY_DATA 1
#DEFINE ENTRY_PATTERN ENTRY_DATA + 1
#DEFINE ENTRY_OFFSET ENTRY_PATTERN + 1
#DEFINE ENTRY_BUTTON ENTRY_OFFSET + 1
#DEFINE ENTRY_RESULTS ENTRY_BUTTON + 1
#DEFINE ENTRY_SPIN ENTRY_RESULTS + 1
#DEFINE ENTRY_POS1 ENTRY_SPIN + 1
#DEFINE ENTRY_POS2 ENTRY_POS1 + 1
#DEFINE ENTRY_STRING ENTRY_POS2 + 1
#DEFINE ENTRY_REGEXP ENTRY_STRING + 1
#DEFINE ENTRY_OFFSET_VALUE ENTRY_REGEXP + 1
#DEFINE ENTRY_CASELESS ENTRY_OFFSET_VALUE + 1
#DEFINE ENTRY_MULTILINE ENTRY_CASELESS + 1
#DEFINE ENTRY_DOTALL ENTRY_MULTILINE + 1
#DEFINE ENTRY_EXTENDED ENTRY_DOTALL + 1
#DEFINE ENTRY_ANCHORED ENTRY_EXTENDED + 1
#DEFINE ENTRY_DOLLAR_ENDONLY ENTRY_ANCHORED + 1
#DEFINE ENTRY_EXTRA ENTRY_DOLLAR_ENDONLY + 1
#DEFINE ENTRY_NOTBOL ENTRY_EXTRA + 1
#DEFINE ENTRY_NOTEOL ENTRY_NOTBOL + 1
#DEFINE ENTRY_UNGREEDY ENTRY_NOTEOL + 1
#DEFINE ENTRY_NOTEMPTY ENTRY_UNGREEDY + 1
#DEFINE ENTRY_UTF8 ENTRY_NOTEMPTY + 1
#INCLUDE "AppEvent.CH"
#INCLUDE "FileIO.CH"
#INCLUDE "Xbp.CH"
#INCLUDE "XbpCRE.CH"
#PRAGMA LIBRARY("XbpCRE.LIB")
FUNCTION Main()
Local mp1, mp2
Local nEvent
Local oXbp
GenDialog()
nEvent := xbe_None
WHILE nEvent <> xbeP_Close
nEvent := AppEvent(@mp1, @mp2, @oXbp)
oXbp:handleEvent(nEvent, mp1, mp2)
END
RETURN (.T.)
FUNCTION GenDialog()
Local aPos, aSize, aBaseSize, aEntries, aPosIn, aSizeIn
Local nSizeHigh, nI
Local oXbp, oDlg, oGroup
oDlg := RootWindow():drawingArea
aBaseSize := oDlg:currentSize()
aEntries := {}
// Erzeugen des Eingabefeldes für den zu durchsuchenden Text
aPos := {10, aBaseSize[2] - 160}
aSize := {aBaseSize[1] - 20, 150}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "enter/drag drop text to search"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpMLE():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:tabStop := .T.
oXbp:ignoreTab := .T.
oXbp:dropZone := .T.
oXbp:dragEnter := {|aState, oData, self| CheckDragDrop(aState, oData, self)}
oXbp:dragDrop := {|aState, oData, self| HandleDragDrop(aState, oData, self)}
oXbp:create()
AAdd(aEntries, oXbp)
// Erzeugen des Eingabefeldes für das Pattern
nSizeHigh := 40
aPos[2] -= nSizeHigh
aPos[2] -= 10
aSize[2] := nSizeHigh
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "enter search pattern (regular expression)"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpSLE():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:tabStop := .T.
oXbp:bufferLength := 256
oXbp:create()
AAdd(aEntries, oXbp)
// Erzeugen des Eingabefeldes für den Offset
// da ein Spinbutton maximal 99.999 abbilden kann, wird ein Textfeld für die
// Eingabe verwendet:
nSizeHigh := 40
aPos[2] -= nSizeHigh
aPos[2] -= 10
aSize := {160, nSizeHigh}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "select offset for search operation"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpSLE():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:tabStop := .T.
oXbp:create()
oXbp:setData("1")
AAdd(aEntries, oXbp)
// Erzeugen eines Pushbuttons, um einen Test auszuführen
nSizeHigh := 30
aPos[2] -= nSizeHigh
aPos[2] -= 10
aSize := {120, nSizeHigh}
oXbp := XbpPushButton():new(oDlg, oDlg, aPos, aSize)
oXbp:caption := "Try it!"
oXbp:tabStop := .T.
oXbp:activate := {|| RunRegExp(aEntries)}
oXbp:create()
AAdd(aEntries, oXbp)
// Anzeige der Matches
nSizeHigh := 40
aPos[2] -= nSizeHigh
aPos[2] -= 10
aSize := {210, nSizeHigh}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "result from executing RegExp"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpStatic():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:type := XBPSTATIC_TYPE_TEXT
oXbp:options := XBPSTATIC_TEXT_CENTER
oXbp:caption := "??"
oXbp:create()
AAdd(aEntries, oXbp)
// Auswahl der Matches über einen Spinbutton
aPos[1] += 10 + aSize[1]
aSize := {180, nSizeHigh}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "result from RegExp:Exec()"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpSpinButton():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:tabStop := .T.
oXbp:down := {|| SwitchDisplay(aEntries)}
oXbp:up := {|| SwitchDisplay(aEntries)}
oXbp:setNumLimits(0, 0)
oXbp:create()
AAdd(aEntries, oXbp)
// Anzeige der Position, wo der Match gefunden wurde
aPos[1] += 10 + aSize[1]
aSize := {100, nSizeHigh}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "starting point"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpStatic():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:type := XBPSTATIC_TYPE_TEXT
oXbp:options := XBPSTATIC_TEXT_CENTER
oXbp:caption := "??"
oXbp:create()
AAdd(aEntries, oXbp)
// Anzeige der Länge des Matches
aPos[1] += 10 + aSize[1]
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "length"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpStatic():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:type := XBPSTATIC_TYPE_TEXT
oXbp:options := XBPSTATIC_TEXT_CENTER
oXbp:caption := "??"
oXbp:create()
AAdd(aEntries, oXbp)
// Anzeige des Ergebnis-Strings (bzw. eines Teils davon)
nSizeHigh := 40
aPos[1] := 10
aPos[2] -= nSizeHigh
aPos[2] -= 10
aSize := {aBaseSize[1] - 20, nSizeHigh}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "result"
oGroup:create()
aPosIn := AClone(aPos)
aSizeIn := AClone(aSize)
ReSizeLocation(aPosIn, aSizeIn)
oXbp := XbpStatic():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:type := XBPSTATIC_TYPE_TEXT
oXbp:options := XBPSTATIC_TEXT_LEFT
oXbp:caption := "??"
oXbp:create()
AAdd(aEntries, oXbp)
// Erzeugen zweiter Platzhalter für das RegExp-Objekt und den Offset
AAdd(aEntries, NIL)
AAdd(aEntries, 1)
// Erzeugen von Checkboxen zum Setzen diverser RegEx-Optionen:
nSizeHigh := 140
aPos[1] := 10
aPos[2] -= nSizeHigh
aPos[2] -= 10
aSize := {aBaseSize[1] - 20, nSizeHigh}
oGroup := XbpStatic():new(oDlg, oDlg, aPos, aSize)
oGroup:type := XBPSTATIC_TYPE_GROUPBOX
oGroup:caption := "PCRE options"
oGroup:create()
nSizeHigh := 30
aPosIn := {10, 95}
aSizeIn := {180, nSizeHigh}
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_CASELESS"
oXbp:create()
AAdd(aEntries, oXbp)
oXbp:setData(.T.)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_MULTILINE"
oXbp:create()
AAdd(aEntries, oXbp)
oXbp:setData(.T.)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_DOTALL"
oXbp:create()
AAdd(aEntries, oXbp)
oXbp:setData(.T.)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_EXTENDED"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] := 10
aPosIn[2] -= aSizeIn[2]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_ANCHORED"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_DOLLAR_ENDONLY"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_EXTRA"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_NOTBOL"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] := 10
aPosIn[2] -= aSizeIn[2]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_NOTEOL"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_UNGREEDY"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_NOTEMPTY"
oXbp:create()
AAdd(aEntries, oXbp)
aPosIn[1] += aSizeIn[1]
oXbp := XbpCheckBox():new(oGroup, oGroup, aPosIn, aSizeIn)
oXbp:caption := "PCRE_UTF8"
oXbp:create()
AAdd(aEntries, oXbp)
SetAppFocus(aEntries[1])
RETURN (.T.)
FUNCTION RunRegExp(aEntries)
Local aPos
Local cData, cPattern, cResult
Local nResult, nRegExpOptions, nOffset
Local oReg
// prüfen, ob Daten eingegeben wurden
cData := aEntries[1]:getData()
IF Empty(cData)
ConfirmBox(, "No data defined for searching, please correct and re-try", "Error", XBPMB_OK, XBPMB_CRITICAL)
RETU(.F.)
ENDIF
// prüfen, ob ein Pattern eingegeben wurde
cPattern := aEntries[2]:getData()
IF Empty(cPattern)
ConfirmBox(, "No search pattern defined, please correct and re-try", "Error", XBPMB_OK, XBPMB_CRITICAL)
RETU(.F.)
ENDIF
// Ermitteln des Offset
nOffset := Val(aEntries[3]:getData())
IF Empty(nOffSet) .OR. nOffSet < 1
nOffSet := 1
ENDIF
// Ermitteln der Optionen, die aktiviert werden sollen:
nRegExpOptions := 0
IF aEntries[ENTRY_CASELESS]:getData()
nRegExpOptions += PCRE_CASELESS
ENDIF
IF aEntries[ENTRY_MULTILINE]:getData()
nRegExpOptions += PCRE_MULTILINE
ENDIF
IF aEntries[ENTRY_DOTALL]:getData()
nRegExpOptions += PCRE_DOTALL
ENDIF
IF aEntries[ENTRY_EXTENDED]:getData()
nRegExpOptions += PCRE_EXTENDED
ENDIF
IF aEntries[ENTRY_ANCHORED]:getData()
nRegExpOptions += PCRE_ANCHORED
ENDIF
IF aEntries[ENTRY_DOLLAR_ENDONLY]:getData()
nRegExpOptions += PCRE_DOLLAR_ENDONLY
ENDIF
IF aEntries[ENTRY_EXTRA]:getData()
nRegExpOptions += PCRE_EXTRA
ENDIF
IF aEntries[ENTRY_NOTBOL]:getData()
nRegExpOptions += PCRE_NOTBOL
ENDIF
IF aEntries[ENTRY_NOTEOL]:getData()
nRegExpOptions += PCRE_NOTEOL
ENDIF
IF aEntries[ENTRY_UNGREEDY]:getData()
nRegExpOptions += PCRE_UNGREEDY
ENDIF
IF aEntries[ENTRY_NOTEMPTY]:getData()
nRegExpOptions += PCRE_NOTEMPTY
ENDIF
IF aEntries[ENTRY_UTF8]:getData()
nRegExpOptions += PCRE_UTF8
ENDIF
// Erzeugen eines RegExp() Objekts, und Ausführung desselben
oReg := RegExp():new(cPattern, nRegExpOptions)
nResult := oReg:exec(cData, nOffSet)
// Darstellung des Ergebnisses in der Maske
cResult := Str(nResult)
aEntries[5]:caption := cResult
aEntries[5]:configure()
// wenn kein Treffer gefunden wurde, werden bestimmte Elemente zurückgesetzt
IF nResult < 1
aEntries[6]:setNumLimits(0, 0)
aEntries[6]:disable()
aEntries[7]:caption := "???"
aEntries[7]:configure()
aEntries[8]:caption := "???"
aEntries[8]:configure()
aEntries[11] := nOffSet
ELSE
// wenn Treffer gefunden wurden, wird das erste Ergebnis angezeigt, und
// die Anzeige weiterer ermöglicht:
aEntries[6]:enable()
aPos := oReg:Result(1)
aEntries[6]:setNumLimits(0, nResult)
aEntries[6]:setData(1)
aEntries[7]:caption := Str(aPos[1])
aEntries[7]:configure()
aEntries[8]:caption := Str(aPos[2])
aEntries[8]:configure()
aEntries[9]:caption := Substr(cData, aPos[1], aPos[2])
aEntries[9]:configure()
aEntries[11] := nOffSet
ENDIF
aEntries[10] := oReg
RETURN (.T.)
FUNCTION SwitchDisplay(aEntries)
Local aPos
Local nValue
// wenn der Spinbutton verändert wurde, wird diese Routine aufgerufen, um die
// korrespondierenden Werte abzurufen:
nValue := aEntries[6]:getData()
IF nValue > 0
aPos := aEntries[10]:Result(nValue)
aEntries[7]:caption := Str(aPos[1])
aEntries[7]:configure()
aEntries[8]:caption := Str(aPos[2])
aEntries[8]:configure()
aEntries[9]:caption := Substr(aEntries[1]:getData(), aPos[1], aPos[2])
aEntries[9]:configure()
ENDIF
RETURN (aEntries)
FUNCTION CheckDragDrop(aState, oData, oMLE)
// nur Text oder eine Dateiliste sind zulässig Objekte, die per Drag and Drop verschoben
// werden können
DO CASE
CASE oData:QueryGetFormat(XBPCLPBRD_FILELIST) == .T.
RETU(XBP_DROPMODE_COPY)
CASE oData:QueryGetFormat(XBPCLPBRD_TEXT) == .T.
RETU(XBP_DROPMODE_COPY)
ENDCASE
RETURN (XBP_DROPMODE_NONE)
FUNCTION HandleDragDrop(aState, oData, oMLE)
// das Feld mit dem Suchtext kann durch Tastatur oder Drag and Drop einer Datei oder eines
// markierten Textes gefüllt werden. Drag and Drop ersetzt vorherige Daten.
Local aFiles
Local cFile, cContent
Local nHandle, nSize
DO CASE
CASE oData:QueryGetFormat(XBPCLPBRD_FILELIST) == .T.
aFiles := oData:GetData(XBPCLPBRD_FILELIST)
cFile := aFiles[1]
nHandle := fOpen(cFile, FO_READ)
IF nHandle < 0
RETU(.F.)
ENDIF
nSize := fSize(nHandle)
cContent := Space(nSize)
fRead(nHandle, @cContent, nSize)
fClose(nHandle)
oMLE:setData(cContent)
CASE oData:QueryGetFormat(XBPCLPBRD_TEXT) == .T.
cContent := oData:getData(XBPCLPBRD_TEXT)
oMLE:setData(cContent)
ENDCASE
RETURN (.T.)
FUNCTION CleanUpAfter()
RETURN (.T.)
FUNCTION GetProgramTitle()
Local cTitle
cTitle := "RegExp-Testlab"
RETURN (cTitle)
FUNCTION ReSizeLocation(aPosIn, aSizeIn)
Local nI
// Ermitteln der Position innerhalb der GroupBox, an der Xbase-Parts angezeigt werden sollen
FOR nI := 1 TO 2
aSizeIn[nI] -= 20
aPosIn[nI] := 5
NEXT
RETURN (.T.)
FUNCTION WinManKill()
RETURN (.T.)
Download
Von der Alaska Website